From 983348fef873f03f2f5efcf8edd34bd258855fe8 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 10 Sep 2024 15:13:32 +0530 Subject: [PATCH 01/57] Setup sub-space screen and routing --- app/lib/common/utils/routes.dart | 1 + .../widgets/space_sections/spaces_section.dart | 2 +- app/lib/features/spaces/pages/sub_spaces.dart | 12 ++++++++++++ .../router/shell_routers/home_shell_router.dart | 14 ++++++++++++++ 4 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 app/lib/features/spaces/pages/sub_spaces.dart diff --git a/app/lib/common/utils/routes.dart b/app/lib/common/utils/routes.dart index c10cb581dcc7..31cb2557d0c4 100644 --- a/app/lib/common/utils/routes.dart +++ b/app/lib/common/utils/routes.dart @@ -66,6 +66,7 @@ enum Routes { spaceInvite('/:spaceId([!#][^/]+)/invite'), space('/:spaceId([!#][^/]+)'), // !spaceId, #spaceName spaceRelatedSpaces('/:spaceId([!#][^/]+)/spaces'), + subSpaces('/:spaceId([!#][^/]+)/subSpaces'), spaceMembers('/:spaceId([!#][^/]+)/members'), spacePins('/:spaceId([!#][^/]+)/pins'), spaceEvents('/:spaceId([!#][^/]+)/events'), diff --git a/app/lib/features/space/widgets/space_sections/spaces_section.dart b/app/lib/features/space/widgets/space_sections/spaces_section.dart index 35625b743ff3..dd6c71db0914 100644 --- a/app/lib/features/space/widgets/space_sections/spaces_section.dart +++ b/app/lib/features/space/widgets/space_sections/spaces_section.dart @@ -62,7 +62,7 @@ class SpacesSection extends ConsumerWidget { title: L10n.of(context).spaces, isShowSeeAllButton: config.isShowSeeAllButton, onTapSeeAll: () => context.pushNamed( - Routes.spaceRelatedSpaces.name, + Routes.subSpaces.name, pathParameters: {'spaceId': spaceId}, ), ), diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart new file mode 100644 index 000000000000..f7cb08415548 --- /dev/null +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -0,0 +1,12 @@ +import 'package:flutter/material.dart'; + +class SubSpaces extends StatelessWidget { + final String spaceId; + + const SubSpaces({super.key, required this.spaceId}); + + @override + Widget build(BuildContext context) { + return const Placeholder(); + } +} diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 352dce09ef5e..3497720af2cc 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -27,6 +27,7 @@ import 'package:acter/features/settings/pages/sessions_page.dart'; import 'package:acter/features/space/pages/space_details_page.dart'; import 'package:acter/features/space/settings/pages/visibility_accessibility_page.dart'; import 'package:acter/features/space/settings/widgets/space_settings_menu.dart'; +import 'package:acter/features/spaces/pages/sub_spaces.dart'; import 'package:acter/features/super_invites/pages/super_invites.dart'; import 'package:acter/features/space/pages/chats_page.dart'; import 'package:acter/features/space/pages/members_page.dart'; @@ -224,6 +225,19 @@ final homeShellRoutes = [ ); }, ), + GoRoute( + name: Routes.subSpaces.name, + path: Routes.subSpaces.route, + redirect: authGuardRedirect, + pageBuilder: (context, state) { + return NoTransitionPage( + key: state.pageKey, + child: SubSpaces( + spaceId: state.pathParameters['spaceId']!, + ), + ); + }, + ), GoRoute( name: Routes.spaceMembers.name, path: Routes.spaceMembers.route, From 2fed2fe2ed6109f4afa8f0720b40a94baf7bc879 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 10 Sep 2024 15:35:40 +0530 Subject: [PATCH 02/57] Setup AppBar Component --- app/lib/features/spaces/pages/sub_spaces.dart | 108 +++++++++++++++++- app/lib/l10n/app_en.arb | 1 + 2 files changed, 106 insertions(+), 3 deletions(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index f7cb08415548..65314aa2a954 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,12 +1,114 @@ +import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/utils/routes.dart'; +import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:go_router/go_router.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; + +class SubSpaces extends ConsumerWidget { + static const moreOptionKey = Key('sub-spaces-more-actions'); + static const createSubspaceKey = Key('sub-spaces-more-create-subspace'); + static const linkSubspaceKey = Key('sub-spaces-more-link-subspace'); -class SubSpaces extends StatelessWidget { final String spaceId; const SubSpaces({super.key, required this.spaceId}); @override - Widget build(BuildContext context) { - return const Placeholder(); + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + appBar: _buildAppBarUI(context, ref), + body: const Placeholder(), + ); + } + + AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { + final spaceName = ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(spaceId)); + bool canLinkSpace = + membership.valueOrNull?.canString('CanLinkSpaces') == true; + return AppBar( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(L10n.of(context).spaces), + Text( + '($spaceName)', + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelLarge, + ), + ], + ), + actions: [ + IconButton( + icon: Icon(PhosphorIcons.arrowsClockwise()), + onPressed: () => ref.invalidate(spaceRelationsProvider), + ), + if (canLinkSpace) _buildMenuOptions(context), + ], + ); + } + + Widget _buildMenuOptions(BuildContext context) { + return PopupMenuButton( + icon: Icon(PhosphorIcons.plusCircle()), + iconSize: 28, + color: Theme.of(context).colorScheme.surface, + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + key: createSubspaceKey, + onTap: () => context.pushNamed( + Routes.createSpace.name, + queryParameters: {'parentSpaceId': spaceId}, + ), + child: Row( + children: [ + Icon(PhosphorIcons.plus()), + const SizedBox(width: 6), + Text(L10n.of(context).createSubspace), + ], + ), + ), + PopupMenuItem( + key: linkSubspaceKey, + onTap: () => context.pushNamed( + Routes.linkSubspace.name, + pathParameters: {'spaceId': spaceId}, + ), + child: Row( + children: [ + Icon(PhosphorIcons.link()), + const SizedBox(width: 6), + Text(L10n.of(context).linkExistingSpace), + ], + ), + ), + PopupMenuItem( + onTap: () => context.pushNamed( + Routes.linkRecommended.name, + pathParameters: {'spaceId': spaceId}, + ), + child: Row( + children: [ + const Icon(Atlas.link_select, size: 18), + const SizedBox(width: 8), + Text(L10n.of(context).recommendedSpaces), + ], + ), + ), + PopupMenuItem( + onTap: () {}, + child: Row( + children: [ + Icon(PhosphorIcons.dotsSixVertical()), + const SizedBox(width: 6), + Text(L10n.of(context).organized), + ], + ), + ), + ], + ); } } diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index a0d40f81b70b..1c4e9f406d56 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2187,6 +2187,7 @@ "updatingIcon": "Updating Icon", "selectColor": "Select color", "selectIcon": "Select icon", + "organized": "Organized", "action": "Action", "@action": {} } From 10927ee5b9bcace55b95e3edd9df54dac5c0a156 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 10 Sep 2024 16:24:05 +0530 Subject: [PATCH 03/57] Setup Categories Data Providers --- app/lib/common/providers/space_providers.dart | 39 +++++++++++++++++++ app/lib/features/spaces/pages/sub_spaces.dart | 34 +++++++++++++--- 2 files changed, 68 insertions(+), 5 deletions(-) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index e4c8fd61b615..dc13ad6310b0 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -49,6 +49,45 @@ final spaceProvider = throw 'Space not found'; }); +final spaceCategoriesProvider = + FutureProvider.family((ref, spaceId) async { + final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); + if (maybeSpace != null) { + return maybeSpace.categories('spaces'); + } + throw 'Space not found'; +}); + +final addDummySpaceCategoriesProvider = + FutureProvider.family((ref, spaceId) async { + final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); + if (maybeSpace != null) { + final categoriesManager = await maybeSpace.categories('spaces'); + + final newCats = categoriesManager.updateBuilder(); + newCats.clear(); + + //NEW CATEGORY-1 + final newCat1 = categoriesManager.newCategoryBuilder(); + newCat1.title('Test Cat - 1'); + newCats.add(newCat1.build()); + + //NEW CATEGORY-2 + final newCat2 = categoriesManager.newCategoryBuilder(); + newCat2.title('Test Cat - 2'); + newCats.add(newCat2.build()); + + //NEW CATEGORY-3 + final newCat3 = categoriesManager.newCategoryBuilder(); + newCat3.title('Test Cat - 3'); + newCats.add(newCat3.build()); + maybeSpace.setCategories('spaces', newCats); + + return maybeSpace.categories('spaces'); + } + throw 'Space not found'; +}); + final spaceIsBookmarkedProvider = FutureProvider.family((ref, spaceId) async { final space = await ref.watch(spaceProvider(spaceId).future); diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 65314aa2a954..cf356373140a 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,12 +1,17 @@ import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:go_router/go_router.dart'; +import 'package:logging/logging.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; +final _log = Logger('a3::space::sub_spaces'); + class SubSpaces extends ConsumerWidget { static const moreOptionKey = Key('sub-spaces-more-actions'); static const createSubspaceKey = Key('sub-spaces-more-create-subspace'); @@ -20,12 +25,13 @@ class SubSpaces extends ConsumerWidget { Widget build(BuildContext context, WidgetRef ref) { return Scaffold( appBar: _buildAppBarUI(context, ref), - body: const Placeholder(), + body: _buildSubSpacesUI(context, ref), ); } AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { - final spaceName = ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; + final spaceName = + ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; final membership = ref.watch(roomMembershipProvider(spaceId)); bool canLinkSpace = membership.valueOrNull?.canString('CanLinkSpaces') == true; @@ -44,7 +50,9 @@ class SubSpaces extends ConsumerWidget { actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () => ref.invalidate(spaceRelationsProvider), + onPressed: () { + ref.read(addDummySpaceCategoriesProvider(spaceId)); + }, ), if (canLinkSpace) _buildMenuOptions(context), ], @@ -58,7 +66,7 @@ class SubSpaces extends ConsumerWidget { color: Theme.of(context).colorScheme.surface, itemBuilder: (BuildContext context) => [ PopupMenuItem( - key: createSubspaceKey, + key: SubSpaces.createSubspaceKey, onTap: () => context.pushNamed( Routes.createSpace.name, queryParameters: {'parentSpaceId': spaceId}, @@ -72,7 +80,7 @@ class SubSpaces extends ConsumerWidget { ), ), PopupMenuItem( - key: linkSubspaceKey, + key: SubSpaces.linkSubspaceKey, onTap: () => context.pushNamed( Routes.linkSubspace.name, pathParameters: {'spaceId': spaceId}, @@ -111,4 +119,20 @@ class SubSpaces extends ConsumerWidget { ], ); } + + Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { + final spaceCategories = ref.watch(spaceCategoriesProvider(spaceId)); + return spaceCategories.when( + data: (categories) { + FfiListCategory categoryList = categories.categories(); + print('Categories ${categoryList.length}'); + return const Placeholder(); + }, + error: (e, s) { + _log.severe('Failed to load the space categories', e, s); + return Center(child: Text(L10n.of(context).loadingFailed(e))); + }, + loading: () => Center(child: Text(L10n.of(context).loading)), + ); + } } From 7cd3c327e1b74d92e768c9ac6e7c05f83d4d9c70 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 11 Sep 2024 10:42:56 +0530 Subject: [PATCH 04/57] Added dummy data for testing --- app/lib/common/providers/space_providers.dart | 4 ++++ app/lib/features/spaces/pages/sub_spaces.dart | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index dc13ad6310b0..b528d22554c0 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -70,16 +70,20 @@ final addDummySpaceCategoriesProvider = //NEW CATEGORY-1 final newCat1 = categoriesManager.newCategoryBuilder(); newCat1.title('Test Cat - 1'); + newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); + newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); newCats.add(newCat1.build()); //NEW CATEGORY-2 final newCat2 = categoriesManager.newCategoryBuilder(); newCat2.title('Test Cat - 2'); + newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); newCats.add(newCat2.build()); //NEW CATEGORY-3 final newCat3 = categoriesManager.newCategoryBuilder(); newCat3.title('Test Cat - 3'); + newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); newCats.add(newCat3.build()); maybeSpace.setCategories('spaces', newCats); diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index cf356373140a..9b22f07a67f8 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -124,7 +124,7 @@ class SubSpaces extends ConsumerWidget { final spaceCategories = ref.watch(spaceCategoriesProvider(spaceId)); return spaceCategories.when( data: (categories) { - FfiListCategory categoryList = categories.categories(); + List categoryList = categories.categories().toList(); print('Categories ${categoryList.length}'); return const Placeholder(); }, From b11e15e892942b0791821eafeb771bf4023f65cc Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 11 Sep 2024 11:40:09 +0530 Subject: [PATCH 05/57] Implemented ExpandedList List to view dummy categories data --- app/lib/features/spaces/pages/sub_spaces.dart | 57 +++++++++++++------ 1 file changed, 41 insertions(+), 16 deletions(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 9b22f07a67f8..4e7ca8fe9448 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -12,7 +12,7 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; final _log = Logger('a3::space::sub_spaces'); -class SubSpaces extends ConsumerWidget { +class SubSpaces extends ConsumerStatefulWidget { static const moreOptionKey = Key('sub-spaces-more-actions'); static const createSubspaceKey = Key('sub-spaces-more-create-subspace'); static const linkSubspaceKey = Key('sub-spaces-more-link-subspace'); @@ -22,17 +22,22 @@ class SubSpaces extends ConsumerWidget { const SubSpaces({super.key, required this.spaceId}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _SubSpacesState(); +} + +class _SubSpacesState extends ConsumerState { + @override + Widget build(BuildContext context) { return Scaffold( - appBar: _buildAppBarUI(context, ref), - body: _buildSubSpacesUI(context, ref), + appBar: _buildAppBarUI(), + body: _buildSubSpacesUI(), ); } - AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { + AppBar _buildAppBarUI() { final spaceName = - ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; - final membership = ref.watch(roomMembershipProvider(spaceId)); + ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(widget.spaceId)); bool canLinkSpace = membership.valueOrNull?.canString('CanLinkSpaces') == true; return AppBar( @@ -51,7 +56,7 @@ class SubSpaces extends ConsumerWidget { IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), onPressed: () { - ref.read(addDummySpaceCategoriesProvider(spaceId)); + ref.read(addDummySpaceCategoriesProvider(widget.spaceId)); }, ), if (canLinkSpace) _buildMenuOptions(context), @@ -69,7 +74,7 @@ class SubSpaces extends ConsumerWidget { key: SubSpaces.createSubspaceKey, onTap: () => context.pushNamed( Routes.createSpace.name, - queryParameters: {'parentSpaceId': spaceId}, + queryParameters: {'parentSpaceId': widget.spaceId}, ), child: Row( children: [ @@ -83,7 +88,7 @@ class SubSpaces extends ConsumerWidget { key: SubSpaces.linkSubspaceKey, onTap: () => context.pushNamed( Routes.linkSubspace.name, - pathParameters: {'spaceId': spaceId}, + pathParameters: {'spaceId': widget.spaceId}, ), child: Row( children: [ @@ -96,7 +101,7 @@ class SubSpaces extends ConsumerWidget { PopupMenuItem( onTap: () => context.pushNamed( Routes.linkRecommended.name, - pathParameters: {'spaceId': spaceId}, + pathParameters: {'spaceId': widget.spaceId}, ), child: Row( children: [ @@ -120,13 +125,19 @@ class SubSpaces extends ConsumerWidget { ); } - Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { - final spaceCategories = ref.watch(spaceCategoriesProvider(spaceId)); + Widget _buildSubSpacesUI() { + final spaceCategories = ref.watch(spaceCategoriesProvider(widget.spaceId)); return spaceCategories.when( data: (categories) { - List categoryList = categories.categories().toList(); - print('Categories ${categoryList.length}'); - return const Placeholder(); + final List categoryList = categories.categories().toList(); + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(categoryList[index]); + }, + ); }, error: (e, s) { _log.severe('Failed to load the space categories', e, s); @@ -135,4 +146,18 @@ class SubSpaces extends ConsumerWidget { loading: () => Center(child: Text(L10n.of(context).loading)), ); } + + Widget _buildCategoriesList(Category category) { + return Card( + child: ExpansionTile( + title: Text(category.title()), + children: List.generate( + category.entries().length, + (index) => ListTile( + title: Text(category.entries()[index]), + ), + ), + ), + ); + } } From 24581e5a04748ac9e8e829b08e559d4d230fd10c Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 11 Sep 2024 11:52:47 +0530 Subject: [PATCH 06/57] Added category icon and color data in dummy list --- app/lib/common/providers/space_providers.dart | 38 +++++++++++++++++-- .../acter_icon_picker/model/acter_icons.dart | 3 ++ app/lib/features/spaces/pages/sub_spaces.dart | 19 +++++++++- 3 files changed, 56 insertions(+), 4 deletions(-) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index b528d22554c0..a4d0ed7fd0dc 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -1,9 +1,12 @@ import 'package:acter/common/providers/notifiers/relations_notifier.dart'; import 'package:acter/common/providers/notifiers/space_notifiers.dart'; import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/sdk_provider.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/features/home/providers/client_providers.dart'; import 'package:acter_avatar/acter_avatar.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:riverpod/riverpod.dart'; @@ -66,27 +69,56 @@ final addDummySpaceCategoriesProvider = final newCats = categoriesManager.updateBuilder(); newCats.clear(); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); - //NEW CATEGORY-1 + /// --------(NEW CATEGORY-1)-------- final newCat1 = categoriesManager.newCategoryBuilder(); + //ADD TITLE newCat1.title('Test Cat - 1'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.red.value); + displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); + newCat1.display(displayBuilder.build()); + + //ADD ENTRIES newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); newCats.add(newCat1.build()); - //NEW CATEGORY-2 + /// --------(NEW CATEGORY-2)-------- final newCat2 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE newCat2.title('Test Cat - 2'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.green.value); + displayBuilder.icon('acter-icon', ActerIcon.airplay.name); + newCat2.display(displayBuilder.build()); + + //ADD ENTRIES newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); newCats.add(newCat2.build()); - //NEW CATEGORY-3 + /// --------(NEW CATEGORY-3)-------- final newCat3 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE newCat3.title('Test Cat - 3'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.blue.value); + displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); + newCat3.display(displayBuilder.build()); + + //ADD ENTRIES newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); newCats.add(newCat3.build()); maybeSpace.setCategories('spaces', newCats); + ref.invalidate(spaceCategoriesProvider); return maybeSpace.categories('spaces'); } throw 'Space not found'; diff --git a/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart b/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart index 6c5a51e8c422..75be1523bc1b 100644 --- a/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart +++ b/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart @@ -152,6 +152,9 @@ enum ActerIcon { static ActerIcon iconForTask(String? name) => iconFor(name) ?? ActerIcon.list; + static ActerIcon iconForCategories(String? name) => + iconFor(name) ?? ActerIcon.list; + static ActerIcon iconForPin(String? name) => iconFor(name) ?? ActerIcon.pin; diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 4e7ca8fe9448..be6c71e7cf4e 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,6 +1,10 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; +import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; @@ -150,7 +154,20 @@ class _SubSpacesState extends ConsumerState { Widget _buildCategoriesList(Category category) { return Card( child: ExpansionTile( - title: Text(category.title()), + title: Row( + children: [ + ActerIconWidget( + iconSize: 24, + color: convertColor( + category.display()?.color(), + iconPickerColors[0], + ), + icon: ActerIcon.iconForCategories(category.display()?.iconStr()), + ), + const SizedBox(width: 6), + Text(category.title()), + ], + ), children: List.generate( category.entries().length, (index) => ListTile( From ae2ee1bdc2f8aed577d3e18bfbebda14eada0508 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 11 Sep 2024 11:56:43 +0530 Subject: [PATCH 07/57] Optimised dummy data function --- app/lib/common/providers/space_providers.dart | 66 ------------------- app/lib/features/spaces/pages/sub_spaces.dart | 64 +++++++++++++++++- 2 files changed, 61 insertions(+), 69 deletions(-) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index a4d0ed7fd0dc..a82da35dee3c 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -1,12 +1,9 @@ import 'package:acter/common/providers/notifiers/relations_notifier.dart'; import 'package:acter/common/providers/notifiers/space_notifiers.dart'; import 'package:acter/common/providers/room_providers.dart'; -import 'package:acter/common/providers/sdk_provider.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/features/home/providers/client_providers.dart'; import 'package:acter_avatar/acter_avatar.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; -import 'package:flutter/material.dart'; import 'package:logging/logging.dart'; import 'package:riverpod/riverpod.dart'; @@ -61,69 +58,6 @@ final spaceCategoriesProvider = throw 'Space not found'; }); -final addDummySpaceCategoriesProvider = - FutureProvider.family((ref, spaceId) async { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - final categoriesManager = await maybeSpace.categories('spaces'); - - final newCats = categoriesManager.updateBuilder(); - newCats.clear(); - final sdk = await ref.watch(sdkProvider.future); - final displayBuilder = sdk.api.newDisplayBuilder(); - - /// --------(NEW CATEGORY-1)-------- - final newCat1 = categoriesManager.newCategoryBuilder(); - //ADD TITLE - newCat1.title('Test Cat - 1'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.red.value); - displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); - newCat1.display(displayBuilder.build()); - - //ADD ENTRIES - newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); - newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); - newCats.add(newCat1.build()); - - /// --------(NEW CATEGORY-2)-------- - final newCat2 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat2.title('Test Cat - 2'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.green.value); - displayBuilder.icon('acter-icon', ActerIcon.airplay.name); - newCat2.display(displayBuilder.build()); - - //ADD ENTRIES - newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); - newCats.add(newCat2.build()); - - /// --------(NEW CATEGORY-3)-------- - final newCat3 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat3.title('Test Cat - 3'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.blue.value); - displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); - newCat3.display(displayBuilder.build()); - - //ADD ENTRIES - newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat3.build()); - maybeSpace.setCategories('spaces', newCats); - - ref.invalidate(spaceCategoriesProvider); - return maybeSpace.categories('spaces'); - } - throw 'Space not found'; -}); - final spaceIsBookmarkedProvider = FutureProvider.family((ref, spaceId) async { final space = await ref.watch(spaceProvider(spaceId).future); diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index be6c71e7cf4e..8abac4dd9e37 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,4 +1,5 @@ import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; @@ -59,9 +60,7 @@ class _SubSpacesState extends ConsumerState { actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () { - ref.read(addDummySpaceCategoriesProvider(widget.spaceId)); - }, + onPressed: () => addDummyData(), ), if (canLinkSpace) _buildMenuOptions(context), ], @@ -177,4 +176,63 @@ class _SubSpacesState extends ConsumerState { ), ); } + + Future addDummyData() async { + final maybeSpace = + await ref.watch(maybeSpaceProvider(widget.spaceId).future); + if (maybeSpace != null) { + final categoriesManager = await maybeSpace.categories('spaces'); + + final newCats = categoriesManager.updateBuilder(); + newCats.clear(); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); + + /// --------(NEW CATEGORY-1)-------- + final newCat1 = categoriesManager.newCategoryBuilder(); + //ADD TITLE + newCat1.title('Test Cat - 1'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.red.value); + displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); + newCat1.display(displayBuilder.build()); + + //ADD ENTRIES + newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); + newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); + newCats.add(newCat1.build()); + + /// --------(NEW CATEGORY-2)-------- + final newCat2 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat2.title('Test Cat - 2'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.green.value); + displayBuilder.icon('acter-icon', ActerIcon.airplay.name); + newCat2.display(displayBuilder.build()); + + //ADD ENTRIES + newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); + newCats.add(newCat2.build()); + + /// --------(NEW CATEGORY-3)-------- + final newCat3 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat3.title('Test Cat - 3'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.blue.value); + displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); + newCat3.display(displayBuilder.build()); + + //ADD ENTRIES + newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat3.build()); + maybeSpace.setCategories('spaces', newCats); + } + } } From 419e84d3165d56c34e6b69427ec0c91d2c7b9ce3 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 11 Sep 2024 10:42:56 +0530 Subject: [PATCH 08/57] Setup Categories List with Dummy Data --- app/lib/common/providers/space_providers.dart | 30 ---- .../acter_icon_picker/model/acter_icons.dart | 3 + app/lib/features/spaces/pages/sub_spaces.dart | 136 +++++++++++++++--- 3 files changed, 121 insertions(+), 48 deletions(-) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index dc13ad6310b0..a82da35dee3c 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -58,36 +58,6 @@ final spaceCategoriesProvider = throw 'Space not found'; }); -final addDummySpaceCategoriesProvider = - FutureProvider.family((ref, spaceId) async { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - final categoriesManager = await maybeSpace.categories('spaces'); - - final newCats = categoriesManager.updateBuilder(); - newCats.clear(); - - //NEW CATEGORY-1 - final newCat1 = categoriesManager.newCategoryBuilder(); - newCat1.title('Test Cat - 1'); - newCats.add(newCat1.build()); - - //NEW CATEGORY-2 - final newCat2 = categoriesManager.newCategoryBuilder(); - newCat2.title('Test Cat - 2'); - newCats.add(newCat2.build()); - - //NEW CATEGORY-3 - final newCat3 = categoriesManager.newCategoryBuilder(); - newCat3.title('Test Cat - 3'); - newCats.add(newCat3.build()); - maybeSpace.setCategories('spaces', newCats); - - return maybeSpace.categories('spaces'); - } - throw 'Space not found'; -}); - final spaceIsBookmarkedProvider = FutureProvider.family((ref, spaceId) async { final space = await ref.watch(spaceProvider(spaceId).future); diff --git a/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart b/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart index 6c5a51e8c422..75be1523bc1b 100644 --- a/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart +++ b/app/lib/common/widgets/acter_icon_picker/model/acter_icons.dart @@ -152,6 +152,9 @@ enum ActerIcon { static ActerIcon iconForTask(String? name) => iconFor(name) ?? ActerIcon.list; + static ActerIcon iconForCategories(String? name) => + iconFor(name) ?? ActerIcon.list; + static ActerIcon iconForPin(String? name) => iconFor(name) ?? ActerIcon.pin; diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index cf356373140a..8abac4dd9e37 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,6 +1,11 @@ import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; +import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; @@ -12,7 +17,7 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; final _log = Logger('a3::space::sub_spaces'); -class SubSpaces extends ConsumerWidget { +class SubSpaces extends ConsumerStatefulWidget { static const moreOptionKey = Key('sub-spaces-more-actions'); static const createSubspaceKey = Key('sub-spaces-more-create-subspace'); static const linkSubspaceKey = Key('sub-spaces-more-link-subspace'); @@ -22,17 +27,22 @@ class SubSpaces extends ConsumerWidget { const SubSpaces({super.key, required this.spaceId}); @override - Widget build(BuildContext context, WidgetRef ref) { + ConsumerState createState() => _SubSpacesState(); +} + +class _SubSpacesState extends ConsumerState { + @override + Widget build(BuildContext context) { return Scaffold( - appBar: _buildAppBarUI(context, ref), - body: _buildSubSpacesUI(context, ref), + appBar: _buildAppBarUI(), + body: _buildSubSpacesUI(), ); } - AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { + AppBar _buildAppBarUI() { final spaceName = - ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; - final membership = ref.watch(roomMembershipProvider(spaceId)); + ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(widget.spaceId)); bool canLinkSpace = membership.valueOrNull?.canString('CanLinkSpaces') == true; return AppBar( @@ -50,9 +60,7 @@ class SubSpaces extends ConsumerWidget { actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () { - ref.read(addDummySpaceCategoriesProvider(spaceId)); - }, + onPressed: () => addDummyData(), ), if (canLinkSpace) _buildMenuOptions(context), ], @@ -69,7 +77,7 @@ class SubSpaces extends ConsumerWidget { key: SubSpaces.createSubspaceKey, onTap: () => context.pushNamed( Routes.createSpace.name, - queryParameters: {'parentSpaceId': spaceId}, + queryParameters: {'parentSpaceId': widget.spaceId}, ), child: Row( children: [ @@ -83,7 +91,7 @@ class SubSpaces extends ConsumerWidget { key: SubSpaces.linkSubspaceKey, onTap: () => context.pushNamed( Routes.linkSubspace.name, - pathParameters: {'spaceId': spaceId}, + pathParameters: {'spaceId': widget.spaceId}, ), child: Row( children: [ @@ -96,7 +104,7 @@ class SubSpaces extends ConsumerWidget { PopupMenuItem( onTap: () => context.pushNamed( Routes.linkRecommended.name, - pathParameters: {'spaceId': spaceId}, + pathParameters: {'spaceId': widget.spaceId}, ), child: Row( children: [ @@ -120,13 +128,19 @@ class SubSpaces extends ConsumerWidget { ); } - Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { - final spaceCategories = ref.watch(spaceCategoriesProvider(spaceId)); + Widget _buildSubSpacesUI() { + final spaceCategories = ref.watch(spaceCategoriesProvider(widget.spaceId)); return spaceCategories.when( data: (categories) { - FfiListCategory categoryList = categories.categories(); - print('Categories ${categoryList.length}'); - return const Placeholder(); + final List categoryList = categories.categories().toList(); + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(categoryList[index]); + }, + ); }, error: (e, s) { _log.severe('Failed to load the space categories', e, s); @@ -135,4 +149,90 @@ class SubSpaces extends ConsumerWidget { loading: () => Center(child: Text(L10n.of(context).loading)), ); } + + Widget _buildCategoriesList(Category category) { + return Card( + child: ExpansionTile( + title: Row( + children: [ + ActerIconWidget( + iconSize: 24, + color: convertColor( + category.display()?.color(), + iconPickerColors[0], + ), + icon: ActerIcon.iconForCategories(category.display()?.iconStr()), + ), + const SizedBox(width: 6), + Text(category.title()), + ], + ), + children: List.generate( + category.entries().length, + (index) => ListTile( + title: Text(category.entries()[index]), + ), + ), + ), + ); + } + + Future addDummyData() async { + final maybeSpace = + await ref.watch(maybeSpaceProvider(widget.spaceId).future); + if (maybeSpace != null) { + final categoriesManager = await maybeSpace.categories('spaces'); + + final newCats = categoriesManager.updateBuilder(); + newCats.clear(); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); + + /// --------(NEW CATEGORY-1)-------- + final newCat1 = categoriesManager.newCategoryBuilder(); + //ADD TITLE + newCat1.title('Test Cat - 1'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.red.value); + displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); + newCat1.display(displayBuilder.build()); + + //ADD ENTRIES + newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); + newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); + newCats.add(newCat1.build()); + + /// --------(NEW CATEGORY-2)-------- + final newCat2 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat2.title('Test Cat - 2'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.green.value); + displayBuilder.icon('acter-icon', ActerIcon.airplay.name); + newCat2.display(displayBuilder.build()); + + //ADD ENTRIES + newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); + newCats.add(newCat2.build()); + + /// --------(NEW CATEGORY-3)-------- + final newCat3 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat3.title('Test Cat - 3'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.blue.value); + displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); + newCat3.display(displayBuilder.build()); + + //ADD ENTRIES + newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat3.build()); + maybeSpace.setCategories('spaces', newCats); + } + } } From 54ef622893c3b649b0b2eae14d5265d82fffdd2f Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Wed, 11 Sep 2024 19:10:28 +0100 Subject: [PATCH 09/57] entries are a vec --- native/acter/api.rsh | 2 +- .../rust_sdk/lib/acter_flutter_sdk_ffi.dart | 41 ++++--------------- 2 files changed, 10 insertions(+), 33 deletions(-) diff --git a/native/acter/api.rsh b/native/acter/api.rsh index 2ceb6bdf69f0..1074e7b95ddb 100644 --- a/native/acter/api.rsh +++ b/native/acter/api.rsh @@ -2045,7 +2045,7 @@ object ActerAppSettingsBuilder { object Category { fn title() -> string; - fn entries() -> string; + fn entries() -> Vec; fn display() -> Option; fn update_builder() -> CategoryBuilder; } diff --git a/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart b/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart index de2b8a148776..221d902c0c10 100644 --- a/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart +++ b/packages/rust_sdk/lib/acter_flutter_sdk_ffi.dart @@ -23931,12 +23931,12 @@ class Api { )>(); late final _categoryEntriesPtr = _lookup< ffi.NativeFunction< - _CategoryEntriesReturn Function( + ffi.IntPtr Function( ffi.IntPtr, )>>("__Category_entries"); late final _categoryEntries = _categoryEntriesPtr.asFunction< - _CategoryEntriesReturn Function( + int Function( int, )>(); late final _categoryDisplayPtr = _lookup< @@ -49112,32 +49112,18 @@ class Category { return tmp2; } - String entries() { + FfiListFfiString entries() { var tmp0 = 0; tmp0 = _box.borrow(); final tmp1 = _api._categoryEntries( tmp0, ); - final tmp3 = tmp1.arg0; - final tmp4 = tmp1.arg1; - final tmp5 = tmp1.arg2; - if (tmp4 == 0) { - print("returning empty string"); - return ""; - } - final ffi.Pointer tmp3_ptr = ffi.Pointer.fromAddress(tmp3); - List tmp3_buf = []; - final tmp3_precast = tmp3_ptr.cast(); - for (int i = 0; i < tmp4; i++) { - int char = tmp3_precast.elementAt(i).value; - tmp3_buf.add(char); - } - final tmp2 = utf8.decode(tmp3_buf, allowMalformed: true); - if (tmp5 > 0) { - final ffi.Pointer tmp3_0; - tmp3_0 = ffi.Pointer.fromAddress(tmp3); - _api.__deallocate(tmp3_0, tmp5 * 1, 1); - } + final tmp3 = tmp1; + final ffi.Pointer tmp3_0 = ffi.Pointer.fromAddress(tmp3); + final tmp3_1 = _Box(_api, tmp3_0, "drop_box_FfiListFfiString"); + tmp3_1._finalizer = _api._registerFinalizer(tmp3_1); + final tmp4 = FfiListFfiString._(_api, tmp3_1); + final tmp2 = tmp4; return tmp2; } @@ -60312,15 +60298,6 @@ class _CategoryTitleReturn extends ffi.Struct { external int arg2; } -class _CategoryEntriesReturn extends ffi.Struct { - @ffi.IntPtr() - external int arg0; - @ffi.UintPtr() - external int arg1; - @ffi.UintPtr() - external int arg2; -} - class _CategoryDisplayReturn extends ffi.Struct { @ffi.Uint8() external int arg0; From e3ba54e655fa1c3bce343f2bf384a9abd98a342c Mon Sep 17 00:00:00 2001 From: Benjamin Kampmann Date: Wed, 11 Sep 2024 19:10:58 +0100 Subject: [PATCH 10/57] Minor usage pattern fix to ensure consistentency and improved memory usage --- app/lib/features/spaces/pages/sub_spaces.dart | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 8abac4dd9e37..1839bcdae2d0 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -151,6 +151,9 @@ class _SubSpacesState extends ConsumerState { } Widget _buildCategoriesList(Category category) { + final entries = category.entries().map((s) => s.toDartString()).toList(); + final display = category.display(); + return Card( child: ExpansionTile( title: Row( @@ -158,19 +161,19 @@ class _SubSpacesState extends ConsumerState { ActerIconWidget( iconSize: 24, color: convertColor( - category.display()?.color(), + display?.color(), iconPickerColors[0], ), - icon: ActerIcon.iconForCategories(category.display()?.iconStr()), + icon: ActerIcon.iconForCategories(display?.iconStr()), ), const SizedBox(width: 6), Text(category.title()), ], ), children: List.generate( - category.entries().length, + entries.length, (index) => ListTile( - title: Text(category.entries()[index]), + title: Text(entries[index]), ), ), ), From 11742d069251804f5a8ab7a858b1a8b49967d363 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 11:17:09 +0530 Subject: [PATCH 11/57] Added space card UI for categories entries data --- app/lib/features/spaces/pages/sub_spaces.dart | 43 +++++++++++-------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 1839bcdae2d0..58c16ed69b1c 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -5,6 +5,7 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; +import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; @@ -152,34 +153,42 @@ class _SubSpacesState extends ConsumerState { Widget _buildCategoriesList(Category category) { final entries = category.entries().map((s) => s.toDartString()).toList(); - final display = category.display(); return Card( child: ExpansionTile( - title: Row( - children: [ - ActerIconWidget( - iconSize: 24, - color: convertColor( - display?.color(), - iconPickerColors[0], - ), - icon: ActerIcon.iconForCategories(display?.iconStr()), - ), - const SizedBox(width: 6), - Text(category.title()), - ], - ), + initiallyExpanded: true, + shape: const Border(), + backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + title: _buildCategoryHeader(category), children: List.generate( entries.length, - (index) => ListTile( - title: Text(entries[index]), + (index) => SpaceCard( + roomId: entries[index], + margin: const EdgeInsets.symmetric(vertical: 6), ), ), ), ); } + Widget _buildCategoryHeader(Category category) { + final display = category.display(); + return Row( + children: [ + ActerIconWidget( + iconSize: 24, + color: convertColor( + display?.color(), + iconPickerColors[0], + ), + icon: ActerIcon.iconForCategories(display?.iconStr()), + ), + const SizedBox(width: 6), + Text(category.title()), + ], + ); + } + Future addDummyData() async { final maybeSpace = await ref.watch(maybeSpaceProvider(widget.spaceId).future); From 81b81b9ab4bfd838b4a6f07d996936fb8823a2a9 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 12:24:45 +0530 Subject: [PATCH 12/57] Added https://pub.dev/packages/drag_and_drop_lists --- .../sub-spaces/category_header_view.dart | 38 ++++++++ .../sub-spaces/draggable_space_list.dart | 95 +++++++++++++++++++ .../pages/{ => sub-spaces}/sub_spaces.dart | 46 +++------ .../shell_routers/home_shell_router.dart | 2 +- app/pubspec.lock | 12 ++- app/pubspec.yaml | 1 + 6 files changed, 159 insertions(+), 35 deletions(-) create mode 100644 app/lib/features/spaces/pages/sub-spaces/category_header_view.dart create mode 100644 app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart rename app/lib/features/spaces/pages/{ => sub-spaces}/sub_spaces.dart (87%) diff --git a/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart b/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart new file mode 100644 index 000000000000..b7bc45690be6 --- /dev/null +++ b/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart @@ -0,0 +1,38 @@ +import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:flutter/material.dart'; + +class CategoryHeaderView extends StatelessWidget { + final Category category; + + const CategoryHeaderView({ + super.key, + required this.category, + }); + + @override + Widget build(BuildContext context) { + return _buildCategoryHeader(); + } + + Widget _buildCategoryHeader() { + final display = category.display(); + return Row( + children: [ + ActerIconWidget( + iconSize: 24, + color: convertColor( + display?.color(), + iconPickerColors[0], + ), + icon: ActerIcon.iconForCategories(display?.iconStr()), + ), + const SizedBox(width: 6), + Text(category.title()), + ], + ); + } +} diff --git a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart new file mode 100644 index 000000000000..53a1ff6e99e1 --- /dev/null +++ b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart @@ -0,0 +1,95 @@ +import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/features/spaces/pages/sub-spaces/category_header_view.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; +import 'package:flutter/material.dart'; + +class DraggableSpaceList extends StatefulWidget { + final List categoryList; + + const DraggableSpaceList({ + super.key, + required this.categoryList, + }); + + @override + State createState() => _DraggableSpaceListState(); +} + +class _DraggableSpaceListState extends State { + List? dragAndDropList; + + @override + void initState() { + super.initState(); + setDragAndDropList(); + } + + void setDragAndDropList() { + setState(() { + dragAndDropList = List.generate(widget.categoryList.length, (index) { + final spaceEntries = widget.categoryList[index] + .entries() + .map((s) => s.toDartString()) + .toList(); + return DragAndDropList( + header: CategoryHeaderView( + category: widget.categoryList[index], + ), + children: List.generate( + spaceEntries.length, + (index) => DragAndDropItem( + child: SpaceCard( + roomId: spaceEntries[index].toString(), + margin: const EdgeInsets.symmetric(vertical: 6), + ), + ), + ), + ); + }); + }); + } + + @override + Widget build(BuildContext context) { + return _buildSubSpacesUIWithDrag(); + } + + Widget _buildSubSpacesUIWithDrag() { + return dragAndDropList == null + ? const SizedBox.shrink() + : Padding( + padding: const EdgeInsets.all(12), + child: DragAndDropLists( + children: dragAndDropList!, + onItemReorder: _onItemReorder, + onListReorder: _onListReorder, + ), + ); + } + + Future _onItemReorder( + int oldItemIndex, + int oldListIndex, + int newItemIndex, + int newListIndex, + ) async { + if (dragAndDropList == null) return; + setState(() { + var movedItem = + dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); + dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); + }); + } + + Future _onListReorder( + int oldListIndex, + int newListIndex, + ) async { + if (dragAndDropList == null) return; + setState(() { + var movedList = dragAndDropList!.removeAt(oldListIndex); + dragAndDropList!.insert(newListIndex, movedList); + }); + } +} diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart similarity index 87% rename from app/lib/features/spaces/pages/sub_spaces.dart rename to app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart index 58c16ed69b1c..c9e483cdf526 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart @@ -2,16 +2,15 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; -import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; +import 'package:acter/features/spaces/pages/sub-spaces/category_header_view.dart'; +import 'package:acter/features/spaces/pages/sub-spaces/draggable_space_list.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:logging/logging.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; @@ -134,14 +133,16 @@ class _SubSpacesState extends ConsumerState { return spaceCategories.when( data: (categories) { final List categoryList = categories.categories().toList(); - return ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: categoryList.length, - itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(categoryList[index]); - }, - ); + return true + ? DraggableSpaceList(categoryList: categoryList) + : ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(categoryList[index]); + }, + ); }, error: (e, s) { _log.severe('Failed to load the space categories', e, s); @@ -153,13 +154,12 @@ class _SubSpacesState extends ConsumerState { Widget _buildCategoriesList(Category category) { final entries = category.entries().map((s) => s.toDartString()).toList(); - return Card( child: ExpansionTile( initiallyExpanded: true, shape: const Border(), backgroundColor: Theme.of(context).colorScheme.secondaryContainer, - title: _buildCategoryHeader(category), + title: CategoryHeaderView(category: category), children: List.generate( entries.length, (index) => SpaceCard( @@ -171,24 +171,6 @@ class _SubSpacesState extends ConsumerState { ); } - Widget _buildCategoryHeader(Category category) { - final display = category.display(); - return Row( - children: [ - ActerIconWidget( - iconSize: 24, - color: convertColor( - display?.color(), - iconPickerColors[0], - ), - icon: ActerIcon.iconForCategories(display?.iconStr()), - ), - const SizedBox(width: 6), - Text(category.title()), - ], - ); - } - Future addDummyData() async { final maybeSpace = await ref.watch(maybeSpaceProvider(widget.spaceId).future); diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 3497720af2cc..9e0a5195c38d 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -27,7 +27,7 @@ import 'package:acter/features/settings/pages/sessions_page.dart'; import 'package:acter/features/space/pages/space_details_page.dart'; import 'package:acter/features/space/settings/pages/visibility_accessibility_page.dart'; import 'package:acter/features/space/settings/widgets/space_settings_menu.dart'; -import 'package:acter/features/spaces/pages/sub_spaces.dart'; +import 'package:acter/features/spaces/pages/sub-spaces/sub_spaces.dart'; import 'package:acter/features/super_invites/pages/super_invites.dart'; import 'package:acter/features/space/pages/chats_page.dart'; import 'package:acter/features/space/pages/members_page.dart'; diff --git a/app/pubspec.lock b/app/pubspec.lock index a0513fead5ab..fc7da26cca5e 100644 --- a/app/pubspec.lock +++ b/app/pubspec.lock @@ -501,6 +501,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.0" + drag_and_drop_lists: + dependency: "direct main" + description: + name: drag_and_drop_lists + sha256: "83fab4a9d4d99d9c683858ac5e1975028d87aa796bf68bfd654b19154004b6bb" + url: "https://pub.dev" + source: hosted + version: "0.4.1" emoji_picker_flutter: dependency: "direct main" description: @@ -2574,10 +2582,10 @@ packages: dependency: transitive description: name: vm_service - sha256: "5c5f338a667b4c644744b661f309fb8080bb94b18a7e91ef1dbd343bed00ed6d" + sha256: f652077d0bdf60abe4c1f6377448e8655008eef28f128bc023f7b5e8dfeb48fc url: "https://pub.dev" source: hosted - version: "14.2.5" + version: "14.2.4" volume_controller: dependency: transitive description: diff --git a/app/pubspec.yaml b/app/pubspec.yaml index d3fed9c0c52e..0cbaec6dd1ef 100644 --- a/app/pubspec.yaml +++ b/app/pubspec.yaml @@ -149,6 +149,7 @@ dependencies: phosphor_flutter: ^2.1.0 device_calendar: ^4.3.3-20240801 quickalert: ^1.1.0 + drag_and_drop_lists: ^0.4.1 dev_dependencies: flutter_test: From aa4ab11b7ebaba961c464d879ab60d7836e74037 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 13:32:02 +0530 Subject: [PATCH 13/57] Manage Organised view toggle --- .../sub-spaces/category_header_view.dart | 5 + .../sub-spaces/draggable_space_list.dart | 12 +- .../spaces/pages/sub-spaces/sub_spaces.dart | 132 ++++++++++++++---- 3 files changed, 118 insertions(+), 31 deletions(-) diff --git a/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart b/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart index b7bc45690be6..a35340eb0716 100644 --- a/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart +++ b/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart @@ -4,13 +4,16 @@ import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter/material.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; class CategoryHeaderView extends StatelessWidget { final Category category; + final bool isShowDragHandle; const CategoryHeaderView({ super.key, required this.category, + this.isShowDragHandle = false, }); @override @@ -32,6 +35,8 @@ class CategoryHeaderView extends StatelessWidget { ), const SizedBox(width: 6), Text(category.title()), + const Spacer(), + if (isShowDragHandle) Icon(PhosphorIcons.dotsSixVertical()), ], ); } diff --git a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart index 53a1ff6e99e1..183390e8597a 100644 --- a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart +++ b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart @@ -3,6 +3,7 @@ import 'package:acter/features/spaces/pages/sub-spaces/category_header_view.dart import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; import 'package:flutter/material.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; class DraggableSpaceList extends StatefulWidget { final List categoryList; @@ -33,8 +34,12 @@ class _DraggableSpaceListState extends State { .map((s) => s.toDartString()) .toList(); return DragAndDropList( - header: CategoryHeaderView( - category: widget.categoryList[index], + header: Padding( + padding: const EdgeInsets.all(14), + child: CategoryHeaderView( + category: widget.categoryList[index], + isShowDragHandle: true, + ), ), children: List.generate( spaceEntries.length, @@ -42,6 +47,7 @@ class _DraggableSpaceListState extends State { child: SpaceCard( roomId: spaceEntries[index].toString(), margin: const EdgeInsets.symmetric(vertical: 6), + trailing: Icon(PhosphorIcons.dotsSixVertical()), ), ), ), @@ -59,7 +65,7 @@ class _DraggableSpaceListState extends State { return dragAndDropList == null ? const SizedBox.shrink() : Padding( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(18), child: DragAndDropLists( children: dragAndDropList!, onItemReorder: _onItemReorder, diff --git a/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart b/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart index c9e483cdf526..a7d21ee6ca16 100644 --- a/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart @@ -31,33 +31,74 @@ class SubSpaces extends ConsumerStatefulWidget { } class _SubSpacesState extends ConsumerState { + final ValueNotifier showOrganizedView = ValueNotifier(false); + @override Widget build(BuildContext context) { - return Scaffold( - appBar: _buildAppBarUI(), - body: _buildSubSpacesUI(), + return SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildAppBarUI(), + Expanded(child: _buildSubSpacesUI()), + ], + ), ); } - AppBar _buildAppBarUI() { - final spaceName = - ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; - final membership = ref.watch(roomMembershipProvider(widget.spaceId)); - bool canLinkSpace = - membership.valueOrNull?.canString('CanLinkSpaces') == true; - return AppBar( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, + Widget _buildAppBarUI() { + return ValueListenableBuilder( + valueListenable: showOrganizedView, + builder: (context, value, child) { + return value ? organizedAppBarUI() : normalAppBarUI(); + }, + ); + } + + Widget organizedAppBarUI() { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: Row( children: [ - Text(L10n.of(context).spaces), Text( - '($spaceName)', - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelLarge, + L10n.of(context).organized, + style: Theme.of(context).textTheme.titleLarge, + ), + const Spacer(), + IconButton( + icon: Icon(PhosphorIcons.x()), + onPressed: () => showOrganizedView.value = false, ), ], ), - actions: [ + ); + } + + Widget normalAppBarUI() { + final spaceName = + ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(widget.spaceId)); + bool canLinkSpace = + membership.valueOrNull?.canString('CanLinkSpaces') == true; + return Row( + children: [ + IconButton( + icon: Icon(PhosphorIcons.arrowLeft()), + onPressed: () => Navigator.pop(context), + ), + const SizedBox(width: 4), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(L10n.of(context).spaces), + Text( + '($spaceName)', + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelLarge, + ), + ], + ), + const Spacer(), IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), onPressed: () => addDummyData(), @@ -115,7 +156,7 @@ class _SubSpacesState extends ConsumerState { ), ), PopupMenuItem( - onTap: () {}, + onTap: () => showOrganizedView.value = !showOrganizedView.value, child: Row( children: [ Icon(PhosphorIcons.dotsSixVertical()), @@ -133,16 +174,21 @@ class _SubSpacesState extends ConsumerState { return spaceCategories.when( data: (categories) { final List categoryList = categories.categories().toList(); - return true - ? DraggableSpaceList(categoryList: categoryList) - : ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: categoryList.length, - itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(categoryList[index]); - }, - ); + return ValueListenableBuilder( + valueListenable: showOrganizedView, + builder: (context, value, child) { + return value + ? DraggableSpaceList(categoryList: categoryList) + : ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(categoryList[index]); + }, + ); + }, + ); }, error: (e, s) { _log.severe('Failed to load the space categories', e, s); @@ -226,6 +272,36 @@ class _SubSpacesState extends ConsumerState { //ADD ENTRIES newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); newCats.add(newCat3.build()); + + /// --------(NEW CATEGORY-4)-------- + final newCat4 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat4.title('Test Cat - 4'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.pinkAccent.value); + displayBuilder.icon('acter-icon', ActerIcon.camera.name); + newCat4.display(displayBuilder.build()); + + //ADD ENTRIES + newCat4.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat4.build()); + + /// --------(NEW CATEGORY-5)-------- + final newCat5 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat5.title('Test Cat - 5'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.orange.value); + displayBuilder.icon('acter-icon', ActerIcon.backpack.name); + newCat5.display(displayBuilder.build()); + + //ADD ENTRIES + newCat5.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat5.build()); maybeSpace.setCategories('spaces', newCats); } } From 9850b669b42f385312f98da1a51d6c6e1a7cc52c Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 14:05:18 +0530 Subject: [PATCH 14/57] Added action buttons in Organised view --- .../sub-spaces/draggable_space_list.dart | 44 ++++++++++++++++++- app/lib/l10n/app_en.arb | 1 + 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart index 183390e8597a..06836a90a00f 100644 --- a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart +++ b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart @@ -4,6 +4,7 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; import 'package:flutter/material.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class DraggableSpaceList extends StatefulWidget { final List categoryList; @@ -58,7 +59,48 @@ class _DraggableSpaceListState extends State { @override Widget build(BuildContext context) { - return _buildSubSpacesUIWithDrag(); + return Stack( + children: [ + _buildSubSpacesUIWithDrag(), + Positioned.fill(child: _buildActionButtons()), + ], + ); + } + + Widget _buildActionButtons() { + final buttonStyle = OutlinedButton.styleFrom( + backgroundColor: Theme.of(context).primaryColor); + return Align( + alignment: Alignment.bottomCenter, + child: Container( + padding: const EdgeInsets.all(20), + margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 30), + decoration: BoxDecoration( + color: Theme.of(context).primaryColor.withOpacity(0.5), + borderRadius: const BorderRadius.all(Radius.circular(12)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () {}, + child: Text(L10n.of(context).createCategory), + ), + ), + const SizedBox(width: 30), + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () {}, + child: Text(L10n.of(context).save), + ), + ), + ], + ), + ), + ); } Widget _buildSubSpacesUIWithDrag() { diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 1c4e9f406d56..0c341b3657ad 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2187,6 +2187,7 @@ "updatingIcon": "Updating Icon", "selectColor": "Select color", "selectIcon": "Select icon", + "createCategory": "Create Category", "organized": "Organized", "action": "Action", "@action": {} From 6b334146064bdff206402809f7b42dbf68d57241 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 16:43:33 +0530 Subject: [PATCH 15/57] Code Refactoring to manage categories in generic way --- app/lib/common/providers/space_providers.dart | 9 - .../categories/draggable_category_list.dart | 183 ++++++++++++++++++ .../providers/categories_providers.dart | 17 ++ .../widgets}/category_header_view.dart | 0 .../sub-spaces/draggable_space_list.dart | 143 -------------- .../pages/{sub-spaces => }/sub_spaces.dart | 141 +++++--------- .../shell_routers/home_shell_router.dart | 2 +- 7 files changed, 250 insertions(+), 245 deletions(-) create mode 100644 app/lib/features/categories/draggable_category_list.dart create mode 100644 app/lib/features/categories/providers/categories_providers.dart rename app/lib/features/{spaces/pages/sub-spaces => categories/widgets}/category_header_view.dart (100%) delete mode 100644 app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart rename app/lib/features/spaces/pages/{sub-spaces => }/sub_spaces.dart (68%) diff --git a/app/lib/common/providers/space_providers.dart b/app/lib/common/providers/space_providers.dart index a82da35dee3c..e4c8fd61b615 100644 --- a/app/lib/common/providers/space_providers.dart +++ b/app/lib/common/providers/space_providers.dart @@ -49,15 +49,6 @@ final spaceProvider = throw 'Space not found'; }); -final spaceCategoriesProvider = - FutureProvider.family((ref, spaceId) async { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - return maybeSpace.categories('spaces'); - } - throw 'Space not found'; -}); - final spaceIsBookmarkedProvider = FutureProvider.family((ref, spaceId) async { final space = await ref.watch(spaceProvider(spaceId).future); diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart new file mode 100644 index 000000000000..e92c230fc090 --- /dev/null +++ b/app/lib/features/categories/draggable_category_list.dart @@ -0,0 +1,183 @@ +import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/widgets/category_header_view.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class DraggableCategoryList extends ConsumerStatefulWidget { + final String spaceId; + final CategoriesFor categoriesFor; + + const DraggableCategoryList({ + super.key, + required this.spaceId, + required this.categoriesFor, + }); + + @override + ConsumerState createState() => + _DraggableCategoriesListState(); +} + +class _DraggableCategoriesListState + extends ConsumerState { + List? dragAndDropList; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => setDragAndDropList()); + } + + void setDragAndDropList() async { + final spaceCategories = await ref.read( + categoriesProvider( + (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), + ).future, + ); + final List categoryList = spaceCategories.categories().toList(); + setDragAndDropListData(categoryList); + } + + void setDragAndDropListData(List categoryList) { + dragAndDropList = List.generate(categoryList.length, (index) { + final spaceEntries = + categoryList[index].entries().map((s) => s.toDartString()).toList(); + return DragAndDropList( + header: Padding( + padding: const EdgeInsets.all(14), + child: CategoryHeaderView( + category: categoryList[index], + isShowDragHandle: true, + ), + ), + children: List.generate( + spaceEntries.length, + (index) => DragAndDropItem( + child: SpaceCard( + roomId: spaceEntries[index].toString(), + margin: const EdgeInsets.symmetric(vertical: 6), + trailing: Icon(PhosphorIcons.dotsSixVertical()), + ), + ), + ), + ); + }); + setState(() {}); + } + + @override + Widget build(BuildContext context) { + return SafeArea( + child: Container( + color: Theme.of(context).colorScheme.primaryContainer, + padding: const EdgeInsets.all(16), + child: Column( + children: [ + _buildAppBarUI(), + const Divider(endIndent: 0, indent: 0), + Expanded( + child: Stack( + children: [ + _buildSubSpacesUIWithDrag(), + Positioned.fill(child: _buildActionButtons()), + ], + ), + ), + ], + ), + ), + ); + } + + Widget _buildAppBarUI() { + return Row( + children: [ + Text( + L10n.of(context).organized, + style: Theme.of(context).textTheme.titleLarge, + ), + const Spacer(), + IconButton( + icon: Icon(PhosphorIcons.x()), + onPressed: () => Navigator.pop(context), + ), + ], + ); + } + + Widget _buildActionButtons() { + final buttonStyle = OutlinedButton.styleFrom( + backgroundColor: Theme.of(context).primaryColor); + return Align( + alignment: Alignment.bottomCenter, + child: Container( + padding: const EdgeInsets.all(18), + margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 30), + decoration: BoxDecoration( + color: Theme.of(context).primaryColor.withOpacity(0.8), + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () => Navigator.pop(context), + child: Text(L10n.of(context).createCategory), + ), + ), + const SizedBox(width: 30), + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () => Navigator.pop(context), + child: Text(L10n.of(context).save), + ), + ), + ], + ), + ), + ); + } + + Widget _buildSubSpacesUIWithDrag() { + return dragAndDropList == null + ? const SizedBox.shrink() + : DragAndDropLists( + children: dragAndDropList!, + onItemReorder: _onItemReorder, + onListReorder: _onListReorder, + ); + } + + Future _onItemReorder( + int oldItemIndex, + int oldListIndex, + int newItemIndex, + int newListIndex, + ) async { + if (dragAndDropList == null) return; + setState(() { + var movedItem = + dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); + dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); + }); + } + + Future _onListReorder( + int oldListIndex, + int newListIndex, + ) async { + if (dragAndDropList == null) return; + setState(() { + var movedList = dragAndDropList!.removeAt(oldListIndex); + dragAndDropList!.insert(newListIndex, movedList); + }); + } +} diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart new file mode 100644 index 000000000000..b0e15809de2b --- /dev/null +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -0,0 +1,17 @@ +import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +enum CategoriesFor { spaces, chats, pins } + +typedef CategoriesInfo = ({String spaceId, CategoriesFor categoriesFor}); + +final categoriesProvider = FutureProvider.family( + (ref, categoryInfo) async { + final maybeSpace = + await ref.watch(maybeSpaceProvider(categoryInfo.spaceId).future); + if (maybeSpace != null) { + return maybeSpace.categories(categoryInfo.categoriesFor.name); + } + throw 'Space not found'; +}); diff --git a/app/lib/features/spaces/pages/sub-spaces/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart similarity index 100% rename from app/lib/features/spaces/pages/sub-spaces/category_header_view.dart rename to app/lib/features/categories/widgets/category_header_view.dart diff --git a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart b/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart deleted file mode 100644 index 06836a90a00f..000000000000 --- a/app/lib/features/spaces/pages/sub-spaces/draggable_space_list.dart +++ /dev/null @@ -1,143 +0,0 @@ -import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter/features/spaces/pages/sub-spaces/category_header_view.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; -import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; -import 'package:flutter/material.dart'; -import 'package:phosphor_flutter/phosphor_flutter.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; - -class DraggableSpaceList extends StatefulWidget { - final List categoryList; - - const DraggableSpaceList({ - super.key, - required this.categoryList, - }); - - @override - State createState() => _DraggableSpaceListState(); -} - -class _DraggableSpaceListState extends State { - List? dragAndDropList; - - @override - void initState() { - super.initState(); - setDragAndDropList(); - } - - void setDragAndDropList() { - setState(() { - dragAndDropList = List.generate(widget.categoryList.length, (index) { - final spaceEntries = widget.categoryList[index] - .entries() - .map((s) => s.toDartString()) - .toList(); - return DragAndDropList( - header: Padding( - padding: const EdgeInsets.all(14), - child: CategoryHeaderView( - category: widget.categoryList[index], - isShowDragHandle: true, - ), - ), - children: List.generate( - spaceEntries.length, - (index) => DragAndDropItem( - child: SpaceCard( - roomId: spaceEntries[index].toString(), - margin: const EdgeInsets.symmetric(vertical: 6), - trailing: Icon(PhosphorIcons.dotsSixVertical()), - ), - ), - ), - ); - }); - }); - } - - @override - Widget build(BuildContext context) { - return Stack( - children: [ - _buildSubSpacesUIWithDrag(), - Positioned.fill(child: _buildActionButtons()), - ], - ); - } - - Widget _buildActionButtons() { - final buttonStyle = OutlinedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor); - return Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: const EdgeInsets.all(20), - margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 30), - decoration: BoxDecoration( - color: Theme.of(context).primaryColor.withOpacity(0.5), - borderRadius: const BorderRadius.all(Radius.circular(12)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () {}, - child: Text(L10n.of(context).createCategory), - ), - ), - const SizedBox(width: 30), - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () {}, - child: Text(L10n.of(context).save), - ), - ), - ], - ), - ), - ); - } - - Widget _buildSubSpacesUIWithDrag() { - return dragAndDropList == null - ? const SizedBox.shrink() - : Padding( - padding: const EdgeInsets.all(18), - child: DragAndDropLists( - children: dragAndDropList!, - onItemReorder: _onItemReorder, - onListReorder: _onListReorder, - ), - ); - } - - Future _onItemReorder( - int oldItemIndex, - int oldListIndex, - int newItemIndex, - int newListIndex, - ) async { - if (dragAndDropList == null) return; - setState(() { - var movedItem = - dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); - dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); - }); - } - - Future _onListReorder( - int oldListIndex, - int newListIndex, - ) async { - if (dragAndDropList == null) return; - setState(() { - var movedList = dragAndDropList!.removeAt(oldListIndex); - dragAndDropList!.insert(newListIndex, movedList); - }); - } -} diff --git a/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart similarity index 68% rename from app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart rename to app/lib/features/spaces/pages/sub_spaces.dart index a7d21ee6ca16..33d1721d90ef 100644 --- a/app/lib/features/spaces/pages/sub-spaces/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -4,8 +4,9 @@ import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter/features/spaces/pages/sub-spaces/category_header_view.dart'; -import 'package:acter/features/spaces/pages/sub-spaces/draggable_space_list.dart'; +import 'package:acter/features/categories/draggable_category_list.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; @@ -17,91 +18,43 @@ import 'package:phosphor_flutter/phosphor_flutter.dart'; final _log = Logger('a3::space::sub_spaces'); -class SubSpaces extends ConsumerStatefulWidget { +class SubSpaces extends ConsumerWidget { static const moreOptionKey = Key('sub-spaces-more-actions'); static const createSubspaceKey = Key('sub-spaces-more-create-subspace'); static const linkSubspaceKey = Key('sub-spaces-more-link-subspace'); - final String spaceId; const SubSpaces({super.key, required this.spaceId}); @override - ConsumerState createState() => _SubSpacesState(); -} - -class _SubSpacesState extends ConsumerState { - final ValueNotifier showOrganizedView = ValueNotifier(false); - - @override - Widget build(BuildContext context) { - return SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - _buildAppBarUI(), - Expanded(child: _buildSubSpacesUI()), - ], - ), - ); - } - - Widget _buildAppBarUI() { - return ValueListenableBuilder( - valueListenable: showOrganizedView, - builder: (context, value, child) { - return value ? organizedAppBarUI() : normalAppBarUI(); - }, + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + appBar: _buildAppBarUI(context, ref), + body: _buildSubSpacesUI(context, ref), ); } - Widget organizedAppBarUI() { - return Padding( - padding: const EdgeInsets.symmetric(horizontal: 20), - child: Row( + AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { + final spaceName = ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(spaceId)); + bool canLinkSpace = + membership.valueOrNull?.canString('CanLinkSpaces') == true; + return AppBar( + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(L10n.of(context).spaces), Text( - L10n.of(context).organized, - style: Theme.of(context).textTheme.titleLarge, - ), - const Spacer(), - IconButton( - icon: Icon(PhosphorIcons.x()), - onPressed: () => showOrganizedView.value = false, + '($spaceName)', + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelLarge, ), ], ), - ); - } - - Widget normalAppBarUI() { - final spaceName = - ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; - final membership = ref.watch(roomMembershipProvider(widget.spaceId)); - bool canLinkSpace = - membership.valueOrNull?.canString('CanLinkSpaces') == true; - return Row( - children: [ - IconButton( - icon: Icon(PhosphorIcons.arrowLeft()), - onPressed: () => Navigator.pop(context), - ), - const SizedBox(width: 4), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(L10n.of(context).spaces), - Text( - '($spaceName)', - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelLarge, - ), - ], - ), - const Spacer(), + actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () => addDummyData(), + onPressed: () => addDummyData(ref), ), if (canLinkSpace) _buildMenuOptions(context), ], @@ -118,7 +71,7 @@ class _SubSpacesState extends ConsumerState { key: SubSpaces.createSubspaceKey, onTap: () => context.pushNamed( Routes.createSpace.name, - queryParameters: {'parentSpaceId': widget.spaceId}, + queryParameters: {'parentSpaceId': spaceId}, ), child: Row( children: [ @@ -132,7 +85,7 @@ class _SubSpacesState extends ConsumerState { key: SubSpaces.linkSubspaceKey, onTap: () => context.pushNamed( Routes.linkSubspace.name, - pathParameters: {'spaceId': widget.spaceId}, + pathParameters: {'spaceId': spaceId}, ), child: Row( children: [ @@ -145,7 +98,7 @@ class _SubSpacesState extends ConsumerState { PopupMenuItem( onTap: () => context.pushNamed( Routes.linkRecommended.name, - pathParameters: {'spaceId': widget.spaceId}, + pathParameters: {'spaceId': spaceId}, ), child: Row( children: [ @@ -156,7 +109,15 @@ class _SubSpacesState extends ConsumerState { ), ), PopupMenuItem( - onTap: () => showOrganizedView.value = !showOrganizedView.value, + onTap: () { + showDialog( + context: context, + builder: (context) => DraggableCategoryList( + spaceId: spaceId, + categoriesFor: CategoriesFor.spaces, + ), + ); + }, child: Row( children: [ Icon(PhosphorIcons.dotsSixVertical()), @@ -169,24 +130,21 @@ class _SubSpacesState extends ConsumerState { ); } - Widget _buildSubSpacesUI() { - final spaceCategories = ref.watch(spaceCategoriesProvider(widget.spaceId)); + Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { + final spaceCategories = ref.watch( + categoriesProvider( + (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), + ), + ); return spaceCategories.when( data: (categories) { final List categoryList = categories.categories().toList(); - return ValueListenableBuilder( - valueListenable: showOrganizedView, - builder: (context, value, child) { - return value - ? DraggableSpaceList(categoryList: categoryList) - : ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: categoryList.length, - itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(categoryList[index]); - }, - ); + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(context, categoryList[index]); }, ); }, @@ -198,7 +156,7 @@ class _SubSpacesState extends ConsumerState { ); } - Widget _buildCategoriesList(Category category) { + Widget _buildCategoriesList(BuildContext context, Category category) { final entries = category.entries().map((s) => s.toDartString()).toList(); return Card( child: ExpansionTile( @@ -217,9 +175,8 @@ class _SubSpacesState extends ConsumerState { ); } - Future addDummyData() async { - final maybeSpace = - await ref.watch(maybeSpaceProvider(widget.spaceId).future); + Future addDummyData(WidgetRef ref) async { + final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); if (maybeSpace != null) { final categoriesManager = await maybeSpace.categories('spaces'); diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 9e0a5195c38d..3497720af2cc 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -27,7 +27,7 @@ import 'package:acter/features/settings/pages/sessions_page.dart'; import 'package:acter/features/space/pages/space_details_page.dart'; import 'package:acter/features/space/settings/pages/visibility_accessibility_page.dart'; import 'package:acter/features/space/settings/widgets/space_settings_menu.dart'; -import 'package:acter/features/spaces/pages/sub-spaces/sub_spaces.dart'; +import 'package:acter/features/spaces/pages/sub_spaces.dart'; import 'package:acter/features/super_invites/pages/super_invites.dart'; import 'package:acter/features/space/pages/chats_page.dart'; import 'package:acter/features/space/pages/members_page.dart'; From fe12753cb67f867385c91308f18a536c0825f990 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 17:35:18 +0530 Subject: [PATCH 16/57] Save updated categories data --- .../categories/actions/save_categories.dart | 52 +++++++++++++++++++ .../categories/draggable_category_list.dart | 29 ++++++++--- .../providers/categories_providers.dart | 5 +- app/lib/features/spaces/pages/sub_spaces.dart | 10 ++-- app/lib/l10n/app_en.arb | 2 + 5 files changed, 85 insertions(+), 13 deletions(-) create mode 100644 app/lib/features/categories/actions/save_categories.dart diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart new file mode 100644 index 000000000000..e552c7bacab9 --- /dev/null +++ b/app/lib/features/categories/actions/save_categories.dart @@ -0,0 +1,52 @@ +import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:flutter/cupertino.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:logging/logging.dart'; + +final _log = Logger('a3::save_categories'); + +void saveCategories( + BuildContext context, + WidgetRef ref, + String spaceId, + CategoriesFor categoriesFor, + List categoryList, +) async { + // Show loading message + EasyLoading.show(status: L10n.of(context).updatingCategories); + try { + //Get category manager + final categoriesManager = await ref.read( + categoryManagerProvider( + (spaceId: spaceId, categoriesFor: categoriesFor), + ).future, + ); + + //Get category builder + final categoryBuilder = categoriesManager.updateBuilder(); + + //Clear category builder data and Add new + categoryBuilder.clear(); + for (int i = 0; i < categoryList.length; i++) { + categoryBuilder.add(categoryList[i]); + } + + //Save category builder + final space = await ref.read(spaceProvider(spaceId).future); + space.setCategories(categoriesFor.name, categoryBuilder); + } catch (e, s) { + _log.severe('Failed to save categories', e, s); + if (!context.mounted) { + EasyLoading.dismiss(); + return; + } + EasyLoading.showError( + L10n.of(context).updatingCategoriesFailed(e), + duration: const Duration(seconds: 3), + ); + } +} diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index e92c230fc090..63c24712fd42 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -1,4 +1,5 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; @@ -26,6 +27,7 @@ class DraggableCategoryList extends ConsumerStatefulWidget { class _DraggableCategoriesListState extends ConsumerState { List? dragAndDropList; + late List categoryList; @override void initState() { @@ -34,16 +36,16 @@ class _DraggableCategoriesListState } void setDragAndDropList() async { - final spaceCategories = await ref.read( - categoriesProvider( + final categoriesManager = await ref.read( + categoryManagerProvider( (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), ).future, ); - final List categoryList = spaceCategories.categories().toList(); - setDragAndDropListData(categoryList); + categoryList = categoriesManager.categories().toList(); + setDragAndDropListData(); } - void setDragAndDropListData(List categoryList) { + void setDragAndDropListData() { dragAndDropList = List.generate(categoryList.length, (index) { final spaceEntries = categoryList[index].entries().map((s) => s.toDartString()).toList(); @@ -136,7 +138,13 @@ class _DraggableCategoriesListState Expanded( child: OutlinedButton( style: buttonStyle, - onPressed: () => Navigator.pop(context), + onPressed: () => saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ), child: Text(L10n.of(context).save), ), ), @@ -167,6 +175,12 @@ class _DraggableCategoriesListState var movedItem = dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); + + var movedCategoryEntry = + categoryList[oldListIndex].entries().remove(oldItemIndex); + categoryList[newListIndex] + .entries() + .insert(newItemIndex, movedCategoryEntry); }); } @@ -178,6 +192,9 @@ class _DraggableCategoriesListState setState(() { var movedList = dragAndDropList!.removeAt(oldListIndex); dragAndDropList!.insert(newListIndex, movedList); + + var movedCategoryList = categoryList.removeAt(oldListIndex); + categoryList.insert(newListIndex, movedCategoryList); }); } } diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart index b0e15809de2b..86a1413ab578 100644 --- a/app/lib/features/categories/providers/categories_providers.dart +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -6,8 +6,9 @@ enum CategoriesFor { spaces, chats, pins } typedef CategoriesInfo = ({String spaceId, CategoriesFor categoriesFor}); -final categoriesProvider = FutureProvider.family( - (ref, categoryInfo) async { +final categoryManagerProvider = + FutureProvider.family( + (ref, categoryInfo) async { final maybeSpace = await ref.watch(maybeSpaceProvider(categoryInfo.spaceId).future); if (maybeSpace != null) { diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 33d1721d90ef..162dc64f7660 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -131,14 +131,14 @@ class SubSpaces extends ConsumerWidget { } Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { - final spaceCategories = ref.watch( - categoriesProvider( + final categoryManager = ref.watch( + categoryManagerProvider( (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), ), ); - return spaceCategories.when( - data: (categories) { - final List categoryList = categories.categories().toList(); + return categoryManager.when( + data: (categoryManagerData) { + final List categoryList = categoryManagerData.categories().toList(); return ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 0c341b3657ad..437a3126d812 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2189,6 +2189,8 @@ "selectIcon": "Select icon", "createCategory": "Create Category", "organized": "Organized", + "updatingCategories": "Updating categories", + "updatingCategoriesFailed": "Updating categories failed {error}", "action": "Action", "@action": {} } From 5a01b6c510a67414c0cdc634939db4ab3d400eac Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 17:43:07 +0530 Subject: [PATCH 17/57] Minor UI Fix --- app/lib/features/spaces/pages/sub_spaces.dart | 1 + 1 file changed, 1 insertion(+) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 162dc64f7660..b7cd6d236f48 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -40,6 +40,7 @@ class SubSpaces extends ConsumerWidget { bool canLinkSpace = membership.valueOrNull?.canString('CanLinkSpaces') == true; return AppBar( + centerTitle: false, title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ From 66efc97735cdc66e089c511108b4bff7e725634c Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 18:17:08 +0530 Subject: [PATCH 18/57] Save categories order --- .../categories/actions/save_categories.dart | 129 +++++++++++++++++- .../categories/draggable_category_list.dart | 20 ++- app/lib/features/spaces/pages/sub_spaces.dart | 101 +------------- 3 files changed, 148 insertions(+), 102 deletions(-) diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index e552c7bacab9..1085eb29c7a7 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -1,7 +1,10 @@ +import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -32,12 +35,26 @@ void saveCategories( //Clear category builder data and Add new categoryBuilder.clear(); for (int i = 0; i < categoryList.length; i++) { - categoryBuilder.add(categoryList[i]); + final Category category = categoryList[i]; + final categoryItemBuilder = category.updateBuilder(); + final newEntries = + category.entries().map((s) => s.toDartString()).toList(); + categoryItemBuilder.clearEntries(); + for (int j = 0; j < newEntries.length; j++) { + categoryItemBuilder.addEntry(newEntries[j]); + } + final newCategoryItem = categoryItemBuilder.build(); + categoryBuilder.add(newCategoryItem); } //Save category builder final space = await ref.read(spaceProvider(spaceId).future); space.setCategories(categoriesFor.name, categoryBuilder); + + EasyLoading.dismiss(); + if (context.mounted) { + Navigator.pop(context); + } } catch (e, s) { _log.severe('Failed to save categories', e, s); if (!context.mounted) { @@ -50,3 +67,113 @@ void saveCategories( ); } } + +Future addDummyData( + BuildContext context, + WidgetRef ref, + String spaceId, +) async { + // Show loading message + EasyLoading.show(status: L10n.of(context).updatingCategories); + try { + final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); + if (maybeSpace != null) { + final categoriesManager = await maybeSpace.categories('spaces'); + + final newCats = categoriesManager.updateBuilder(); + newCats.clear(); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); + + /// --------(NEW CATEGORY-1)-------- + final newCat1 = categoriesManager.newCategoryBuilder(); + //ADD TITLE + newCat1.title('Test Cat - 1'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.red.value); + displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); + newCat1.display(displayBuilder.build()); + + //ADD ENTRIES + newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); + newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); + newCats.add(newCat1.build()); + + /// --------(NEW CATEGORY-2)-------- + final newCat2 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat2.title('Test Cat - 2'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.green.value); + displayBuilder.icon('acter-icon', ActerIcon.airplay.name); + newCat2.display(displayBuilder.build()); + + //ADD ENTRIES + newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); + newCats.add(newCat2.build()); + + /// --------(NEW CATEGORY-3)-------- + final newCat3 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat3.title('Test Cat - 3'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.blue.value); + displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); + newCat3.display(displayBuilder.build()); + + //ADD ENTRIES + newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat3.build()); + + /// --------(NEW CATEGORY-4)-------- + final newCat4 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat4.title('Test Cat - 4'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.pinkAccent.value); + displayBuilder.icon('acter-icon', ActerIcon.camera.name); + newCat4.display(displayBuilder.build()); + + //ADD ENTRIES + newCat4.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat4.build()); + + /// --------(NEW CATEGORY-5)-------- + final newCat5 = categoriesManager.newCategoryBuilder(); + + //ADD TITLE + newCat5.title('Test Cat - 5'); + + //ADD COLOR AND ICON + displayBuilder.color(Colors.orange.value); + displayBuilder.icon('acter-icon', ActerIcon.backpack.name); + newCat5.display(displayBuilder.build()); + + //ADD ENTRIES + newCat5.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); + newCats.add(newCat5.build()); + maybeSpace.setCategories('spaces', newCats); + } + if (context.mounted) { + EasyLoading.dismiss(); + return; + } + } catch (e, s) { + _log.severe('Failed to update categories', e, s); + if (context.mounted) { + EasyLoading.dismiss(); + EasyLoading.showError( + L10n.of(context).updatingCategoriesFailed(e), + duration: const Duration(seconds: 3), + ); + return; + } + } +} diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 63c24712fd42..71ec6e55074a 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -114,7 +114,8 @@ class _DraggableCategoriesListState Widget _buildActionButtons() { final buttonStyle = OutlinedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor); + backgroundColor: Theme.of(context).primaryColor, + ); return Align( alignment: Alignment.bottomCenter, child: Container( @@ -176,11 +177,18 @@ class _DraggableCategoriesListState dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); - var movedCategoryEntry = - categoryList[oldListIndex].entries().remove(oldItemIndex); - categoryList[newListIndex] - .entries() - .insert(newItemIndex, movedCategoryEntry); + final oldCategoryItem = categoryList[oldListIndex]; + final spaceEntries = + oldCategoryItem.entries().map((s) => s.toDartString()).toList(); + var movedCategoryEntry = spaceEntries.removeAt(oldItemIndex); + spaceEntries.insert(newItemIndex, movedCategoryEntry); + final categoryItemBuilder = oldCategoryItem.updateBuilder(); + categoryItemBuilder.clearEntries(); + for (int j = 0; j < spaceEntries.length; j++) { + categoryItemBuilder.addEntry(spaceEntries[j]); + } + final newCategoryItem = categoryItemBuilder.build(); + categoryList[oldListIndex] = newCategoryItem; }); } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index b7cd6d236f48..867ad3990a9f 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,9 +1,7 @@ import 'package:acter/common/providers/room_providers.dart'; -import 'package:acter/common/providers/sdk_provider.dart'; -import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/draggable_category_list.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; @@ -54,8 +52,8 @@ class SubSpaces extends ConsumerWidget { ), actions: [ IconButton( - icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () => addDummyData(ref), + icon: Icon(PhosphorIcons.plusCircle()), + onPressed: () => addDummyData(context, ref, spaceId), ), if (canLinkSpace) _buildMenuOptions(context), ], @@ -64,7 +62,7 @@ class SubSpaces extends ConsumerWidget { Widget _buildMenuOptions(BuildContext context) { return PopupMenuButton( - icon: Icon(PhosphorIcons.plusCircle()), + icon: Icon(PhosphorIcons.dotsThreeVertical()), iconSize: 28, color: Theme.of(context).colorScheme.surface, itemBuilder: (BuildContext context) => [ @@ -139,7 +137,8 @@ class SubSpaces extends ConsumerWidget { ); return categoryManager.when( data: (categoryManagerData) { - final List categoryList = categoryManagerData.categories().toList(); + final List categoryList = + categoryManagerData.categories().toList(); return ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, @@ -175,92 +174,4 @@ class SubSpaces extends ConsumerWidget { ), ); } - - Future addDummyData(WidgetRef ref) async { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - final categoriesManager = await maybeSpace.categories('spaces'); - - final newCats = categoriesManager.updateBuilder(); - newCats.clear(); - final sdk = await ref.watch(sdkProvider.future); - final displayBuilder = sdk.api.newDisplayBuilder(); - - /// --------(NEW CATEGORY-1)-------- - final newCat1 = categoriesManager.newCategoryBuilder(); - //ADD TITLE - newCat1.title('Test Cat - 1'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.red.value); - displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); - newCat1.display(displayBuilder.build()); - - //ADD ENTRIES - newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); - newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); - newCats.add(newCat1.build()); - - /// --------(NEW CATEGORY-2)-------- - final newCat2 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat2.title('Test Cat - 2'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.green.value); - displayBuilder.icon('acter-icon', ActerIcon.airplay.name); - newCat2.display(displayBuilder.build()); - - //ADD ENTRIES - newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); - newCats.add(newCat2.build()); - - /// --------(NEW CATEGORY-3)-------- - final newCat3 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat3.title('Test Cat - 3'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.blue.value); - displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); - newCat3.display(displayBuilder.build()); - - //ADD ENTRIES - newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat3.build()); - - /// --------(NEW CATEGORY-4)-------- - final newCat4 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat4.title('Test Cat - 4'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.pinkAccent.value); - displayBuilder.icon('acter-icon', ActerIcon.camera.name); - newCat4.display(displayBuilder.build()); - - //ADD ENTRIES - newCat4.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat4.build()); - - /// --------(NEW CATEGORY-5)-------- - final newCat5 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat5.title('Test Cat - 5'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.orange.value); - displayBuilder.icon('acter-icon', ActerIcon.backpack.name); - newCat5.display(displayBuilder.build()); - - //ADD ENTRIES - newCat5.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat5.build()); - maybeSpace.setCategories('spaces', newCats); - } - } } From ec58103c9cd1d82c13e3c654ba1ba6a99d436e21 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 19:03:49 +0530 Subject: [PATCH 19/57] Updated dummy categories data --- .../categories/actions/save_categories.dart | 30 +------------------ .../categories/draggable_category_list.dart | 18 +++++++++-- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index 1085eb29c7a7..d5c132033fa3 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -113,6 +113,7 @@ Future addDummyData( //ADD ENTRIES newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); + newCat2.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); newCats.add(newCat2.build()); /// --------(NEW CATEGORY-3)-------- @@ -130,35 +131,6 @@ Future addDummyData( newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); newCats.add(newCat3.build()); - /// --------(NEW CATEGORY-4)-------- - final newCat4 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat4.title('Test Cat - 4'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.pinkAccent.value); - displayBuilder.icon('acter-icon', ActerIcon.camera.name); - newCat4.display(displayBuilder.build()); - - //ADD ENTRIES - newCat4.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat4.build()); - - /// --------(NEW CATEGORY-5)-------- - final newCat5 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat5.title('Test Cat - 5'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.orange.value); - displayBuilder.icon('acter-icon', ActerIcon.backpack.name); - newCat5.display(displayBuilder.build()); - - //ADD ENTRIES - newCat5.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat5.build()); maybeSpace.setCategories('spaces', newCats); } if (context.mounted) { diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 71ec6e55074a..77db60c1f94e 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -177,18 +177,32 @@ class _DraggableCategoriesListState dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); + //GET OLDER CATEGORY ITEM final oldCategoryItem = categoryList[oldListIndex]; + + //GET OLDER CATEGORY ITEM DATA IN LOCAL final spaceEntries = - oldCategoryItem.entries().map((s) => s.toDartString()).toList(); + oldCategoryItem.entries().map((s) => s.toDartString()).toList(); + + //REMOVE SPACE ENTRY FROM SPECIFIED POSITION var movedCategoryEntry = spaceEntries.removeAt(oldItemIndex); + + //ADD SPACE ENTRY FROM SPECIFIED POSITION spaceEntries.insert(newItemIndex, movedCategoryEntry); + + //UPDATE CATEGORY ITEM final categoryItemBuilder = oldCategoryItem.updateBuilder(); categoryItemBuilder.clearEntries(); for (int j = 0; j < spaceEntries.length; j++) { categoryItemBuilder.addEntry(spaceEntries[j]); } + + //REMOVE OLDER CATEGORY ITEM FROM SPECIFIED POSITION + categoryList.removeAt(oldListIndex); + + //SAVE NEW CATEGORY ITEM AT SPECIFIED POSITION final newCategoryItem = categoryItemBuilder.build(); - categoryList[oldListIndex] = newCategoryItem; + categoryList.insert(newListIndex, newCategoryItem); }); } From febaec4f7ec70919831e4262cb30d2bf04881be7 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 12 Sep 2024 19:41:53 +0530 Subject: [PATCH 20/57] Fixes the bug related to category order management --- .../categories/draggable_category_list.dart | 78 ++++++++++++++----- 1 file changed, 58 insertions(+), 20 deletions(-) diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 77db60c1f94e..ebf2a4eacac5 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -177,32 +177,70 @@ class _DraggableCategoriesListState dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); - //GET OLDER CATEGORY ITEM - final oldCategoryItem = categoryList[oldListIndex]; + ///MOVE ENTRY ITEM ON SAME CATEGORY + if (oldListIndex == newListIndex) { + //GET OLDER CATEGORY ITEM + final oldCategoryItem = categoryList[oldListIndex]; - //GET OLDER CATEGORY ITEM DATA IN LOCAL - final spaceEntries = - oldCategoryItem.entries().map((s) => s.toDartString()).toList(); + //GET OLDER CATEGORY ITEM DATA IN LOCAL + final spaceEntries = + oldCategoryItem.entries().map((s) => s.toDartString()).toList(); - //REMOVE SPACE ENTRY FROM SPECIFIED POSITION - var movedCategoryEntry = spaceEntries.removeAt(oldItemIndex); + //REMOVE SPACE ENTRY FROM SPECIFIED POSITION + var movedEntryItem = spaceEntries.removeAt(oldItemIndex); - //ADD SPACE ENTRY FROM SPECIFIED POSITION - spaceEntries.insert(newItemIndex, movedCategoryEntry); + //ADD SPACE ENTRY FROM SPECIFIED POSITION + spaceEntries.insert(newItemIndex, movedEntryItem); - //UPDATE CATEGORY ITEM - final categoryItemBuilder = oldCategoryItem.updateBuilder(); - categoryItemBuilder.clearEntries(); - for (int j = 0; j < spaceEntries.length; j++) { - categoryItemBuilder.addEntry(spaceEntries[j]); - } + //UPDATE CATEGORY ITEM + final categoryItemBuilder = oldCategoryItem.updateBuilder(); + categoryItemBuilder.clearEntries(); + for (int j = 0; j < spaceEntries.length; j++) { + categoryItemBuilder.addEntry(spaceEntries[j]); + } + + //REMOVE OLDER CATEGORY ITEM FROM SPECIFIED POSITION + categoryList.removeAt(oldListIndex); + + //SAVE NEW CATEGORY ITEM AT SPECIFIED POSITION + final newCategoryItem = categoryItemBuilder.build(); + categoryList.insert(newListIndex, newCategoryItem); + } else { + ///MOVE ENTRY ITEM NOT ON SAME CATEGORY + final oldCategoryItem = categoryList[oldListIndex]; + + //GET OLDER CATEGORY ITEM DATA IN LOCAL + final oldCategoryItemSpaceEntries = + oldCategoryItem.entries().map((s) => s.toDartString()).toList(); - //REMOVE OLDER CATEGORY ITEM FROM SPECIFIED POSITION - categoryList.removeAt(oldListIndex); + //REMOVE SPACE ENTRY FROM SPECIFIED POSITION + var movedEntryItem = oldCategoryItemSpaceEntries.removeAt(oldItemIndex); - //SAVE NEW CATEGORY ITEM AT SPECIFIED POSITION - final newCategoryItem = categoryItemBuilder.build(); - categoryList.insert(newListIndex, newCategoryItem); + //UPDATE OLD CATEGORY ITEM + final oldCategoryItemBuilder = oldCategoryItem.updateBuilder(); + oldCategoryItemBuilder.clearEntries(); + for (int j = 0; j < oldCategoryItemSpaceEntries.length; j++) { + oldCategoryItemBuilder.addEntry(oldCategoryItemSpaceEntries[j]); + } + categoryList[oldListIndex] = oldCategoryItemBuilder.build(); + + final newCategoryItem = categoryList[newListIndex]; + + //GET NEW CATEGORY ITEM DATA IN LOCAL + final newCategoryItemSpaceEntries = + newCategoryItem.entries().map((s) => s.toDartString()).toList(); + + //REMOVE SPACE ENTRY FROM SPECIFIED POSITION + newCategoryItemSpaceEntries.insert(newItemIndex, movedEntryItem); + + //UPDATE OLD CATEGORY ITEM + final newCategoryItemBuilder = newCategoryItem.updateBuilder(); + newCategoryItemBuilder.clearEntries(); + for (int j = 0; j < newCategoryItemSpaceEntries.length; j++) { + newCategoryItemBuilder.addEntry(newCategoryItemSpaceEntries[j]); + } + categoryList[newListIndex] = newCategoryItemBuilder.build(); + } }); } From 44fa3d90bb4bb17a3c7a486d0b6c7d3a371a4687 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Mon, 16 Sep 2024 18:08:31 +0530 Subject: [PATCH 21/57] Improve code structure by using LocalCategory Model class to manage category data --- .../categories/actions/save_categories.dart | 35 ++++---- .../categories/draggable_category_list.dart | 88 +++---------------- .../categories/model/CategoryModelLocal.dart | 17 ++++ .../categories/utils/category_utils.dart | 29 ++++++ .../widgets/category_header_view.dart | 19 ++-- app/lib/features/spaces/pages/sub_spaces.dart | 33 +++++-- .../spaces/providers/space_list_provider.dart | 21 +++++ 7 files changed, 134 insertions(+), 108 deletions(-) create mode 100644 app/lib/features/categories/model/CategoryModelLocal.dart create mode 100644 app/lib/features/categories/utils/category_utils.dart create mode 100644 app/lib/features/spaces/providers/space_list_provider.dart diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index d5c132033fa3..a056a97f5457 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -1,9 +1,8 @@ import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -17,7 +16,7 @@ void saveCategories( WidgetRef ref, String spaceId, CategoriesFor categoriesFor, - List categoryList, + List categoryList, ) async { // Show loading message EasyLoading.show(status: L10n.of(context).updatingCategories); @@ -28,28 +27,34 @@ void saveCategories( (spaceId: spaceId, categoriesFor: categoriesFor), ).future, ); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); //Get category builder - final categoryBuilder = categoriesManager.updateBuilder(); + final categoriesBuilder = categoriesManager.updateBuilder(); //Clear category builder data and Add new - categoryBuilder.clear(); + categoriesBuilder.clear(); for (int i = 0; i < categoryList.length; i++) { - final Category category = categoryList[i]; - final categoryItemBuilder = category.updateBuilder(); - final newEntries = - category.entries().map((s) => s.toDartString()).toList(); - categoryItemBuilder.clearEntries(); - for (int j = 0; j < newEntries.length; j++) { - categoryItemBuilder.addEntry(newEntries[j]); + final newCategoryItem = categoriesManager.newCategoryBuilder(); + //ADD TITLE + newCategoryItem.title(categoryList[i].title); + + //ADD COLOR AND ICON + displayBuilder.color(categoryList[i].color.value); + displayBuilder.icon('acter-icon', categoryList[i].icon.name); + newCategoryItem.display(displayBuilder.build()); + + //ADD ENTRIES + for (int j = 0; j < categoryList[i].entries.length; j++) { + newCategoryItem.addEntry(categoryList[i].entries[j]); } - final newCategoryItem = categoryItemBuilder.build(); - categoryBuilder.add(newCategoryItem); + categoriesBuilder.add(newCategoryItem.build()); } //Save category builder final space = await ref.read(spaceProvider(spaceId).future); - space.setCategories(categoriesFor.name, categoryBuilder); + space.setCategories(categoriesFor.name, categoriesBuilder); EasyLoading.dismiss(); if (context.mounted) { diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index ebf2a4eacac5..495b3eef3068 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -1,8 +1,9 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -27,7 +28,7 @@ class DraggableCategoryList extends ConsumerStatefulWidget { class _DraggableCategoriesListState extends ConsumerState { List? dragAndDropList; - late List categoryList; + late List categoryList; @override void initState() { @@ -41,27 +42,27 @@ class _DraggableCategoriesListState (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), ).future, ); - categoryList = categoriesManager.categories().toList(); + categoryList = + getLocalCategoryList(categoriesManager.categories().toList()); setDragAndDropListData(); } void setDragAndDropListData() { - dragAndDropList = List.generate(categoryList.length, (index) { - final spaceEntries = - categoryList[index].entries().map((s) => s.toDartString()).toList(); + dragAndDropList = List.generate(categoryList.length, (indexCategory) { return DragAndDropList( header: Padding( padding: const EdgeInsets.all(14), child: CategoryHeaderView( - category: categoryList[index], + categoryModelLocal: categoryList[indexCategory], isShowDragHandle: true, ), ), children: List.generate( - spaceEntries.length, - (index) => DragAndDropItem( + categoryList[indexCategory].entries.length, + (indexEntry) => DragAndDropItem( child: SpaceCard( - roomId: spaceEntries[index].toString(), + roomId: + categoryList[indexCategory].entries[indexEntry].toString(), margin: const EdgeInsets.symmetric(vertical: 6), trailing: Icon(PhosphorIcons.dotsSixVertical()), ), @@ -177,70 +178,9 @@ class _DraggableCategoriesListState dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); - ///MOVE ENTRY ITEM ON SAME CATEGORY - if (oldListIndex == newListIndex) { - //GET OLDER CATEGORY ITEM - final oldCategoryItem = categoryList[oldListIndex]; - - //GET OLDER CATEGORY ITEM DATA IN LOCAL - final spaceEntries = - oldCategoryItem.entries().map((s) => s.toDartString()).toList(); - - //REMOVE SPACE ENTRY FROM SPECIFIED POSITION - var movedEntryItem = spaceEntries.removeAt(oldItemIndex); - - //ADD SPACE ENTRY FROM SPECIFIED POSITION - spaceEntries.insert(newItemIndex, movedEntryItem); - - //UPDATE CATEGORY ITEM - final categoryItemBuilder = oldCategoryItem.updateBuilder(); - categoryItemBuilder.clearEntries(); - for (int j = 0; j < spaceEntries.length; j++) { - categoryItemBuilder.addEntry(spaceEntries[j]); - } - - //REMOVE OLDER CATEGORY ITEM FROM SPECIFIED POSITION - categoryList.removeAt(oldListIndex); - - //SAVE NEW CATEGORY ITEM AT SPECIFIED POSITION - final newCategoryItem = categoryItemBuilder.build(); - categoryList.insert(newListIndex, newCategoryItem); - } else { - ///MOVE ENTRY ITEM NOT ON SAME CATEGORY - final oldCategoryItem = categoryList[oldListIndex]; - - //GET OLDER CATEGORY ITEM DATA IN LOCAL - final oldCategoryItemSpaceEntries = - oldCategoryItem.entries().map((s) => s.toDartString()).toList(); - - //REMOVE SPACE ENTRY FROM SPECIFIED POSITION - var movedEntryItem = oldCategoryItemSpaceEntries.removeAt(oldItemIndex); - - //UPDATE OLD CATEGORY ITEM - final oldCategoryItemBuilder = oldCategoryItem.updateBuilder(); - oldCategoryItemBuilder.clearEntries(); - for (int j = 0; j < oldCategoryItemSpaceEntries.length; j++) { - oldCategoryItemBuilder.addEntry(oldCategoryItemSpaceEntries[j]); - } - categoryList[oldListIndex] = oldCategoryItemBuilder.build(); - - final newCategoryItem = categoryList[newListIndex]; - - //GET NEW CATEGORY ITEM DATA IN LOCAL - final newCategoryItemSpaceEntries = - newCategoryItem.entries().map((s) => s.toDartString()).toList(); - - //REMOVE SPACE ENTRY FROM SPECIFIED POSITION - newCategoryItemSpaceEntries.insert(newItemIndex, movedEntryItem); - - //UPDATE OLD CATEGORY ITEM - final newCategoryItemBuilder = newCategoryItem.updateBuilder(); - newCategoryItemBuilder.clearEntries(); - for (int j = 0; j < newCategoryItemSpaceEntries.length; j++) { - newCategoryItemBuilder.addEntry(newCategoryItemSpaceEntries[j]); - } - categoryList[newListIndex] = newCategoryItemBuilder.build(); - } + var movedEntryItem = + categoryList[oldListIndex].entries.removeAt(oldItemIndex); + categoryList[newListIndex].entries.insert(newItemIndex, movedEntryItem); }); } diff --git a/app/lib/features/categories/model/CategoryModelLocal.dart b/app/lib/features/categories/model/CategoryModelLocal.dart new file mode 100644 index 000000000000..2c3f3803f34c --- /dev/null +++ b/app/lib/features/categories/model/CategoryModelLocal.dart @@ -0,0 +1,17 @@ +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:flutter/material.dart'; + +class CategoryModelLocal { + final String title; + final Color color; + final ActerIcon icon; + final List entries; + + const CategoryModelLocal({ + required this.title, + required this.color, + required this.icon, + required this.entries, + }); +} + diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart new file mode 100644 index 000000000000..14e18e5d3794 --- /dev/null +++ b/app/lib/features/categories/utils/category_utils.dart @@ -0,0 +1,29 @@ +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; +import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; + +List getLocalCategoryList(List categoryList) { + List categoryListLocal = []; + for (var categoryItem in categoryList) { + final title = categoryItem.title(); + final color = convertColor( + categoryItem.display()?.color(), + iconPickerColors[0], + ); + final icon = ActerIcon.iconForPin(categoryItem.display()?.iconStr()); + final entries = + categoryItem.entries().map((s) => s.toDartString()).toList(); + + CategoryModelLocal categoryModelLocal = CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: entries, + ); + categoryListLocal.add(categoryModelLocal); + } + + return categoryListLocal; +} diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index a35340eb0716..0742a435e9dd 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -1,18 +1,15 @@ import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:flutter/material.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; class CategoryHeaderView extends StatelessWidget { - final Category category; + final CategoryModelLocal categoryModelLocal; final bool isShowDragHandle; const CategoryHeaderView({ super.key, - required this.category, + required this.categoryModelLocal, this.isShowDragHandle = false, }); @@ -22,19 +19,15 @@ class CategoryHeaderView extends StatelessWidget { } Widget _buildCategoryHeader() { - final display = category.display(); return Row( children: [ ActerIconWidget( iconSize: 24, - color: convertColor( - display?.color(), - iconPickerColors[0], - ), - icon: ActerIcon.iconForCategories(display?.iconStr()), + color: categoryModelLocal.color, + icon: categoryModelLocal.icon, ), const SizedBox(width: 6), - Text(category.title()), + Text(categoryModelLocal.title), const Spacer(), if (isShowDragHandle) Icon(PhosphorIcons.dotsSixVertical()), ], diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 867ad3990a9f..5f933de5c05c 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -3,9 +3,10 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/draggable_category_list.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; -import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -135,10 +136,30 @@ class SubSpaces extends ConsumerWidget { (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), ), ); + // final subSpaceList = ref.watch(subSpacesListProvider(spaceId)); + // + // return subSpaceList.when( + // data: (subSpaceListData) { + // return ListView.builder( + // scrollDirection: Axis.vertical, + // shrinkWrap: true, + // itemCount: subSpaceListData.length, + // itemBuilder: (BuildContext context, int index) { + // return SpaceCard(roomId: subSpaceListData[index]); + // }, + // ); + // }, + // error: (e, s) { + // _log.severe('Failed to load the space categories', e, s); + // return Center(child: Text(L10n.of(context).loadingFailed(e))); + // }, + // loading: () => Center(child: Text(L10n.of(context).loading)), + // ); + return categoryManager.when( data: (categoryManagerData) { - final List categoryList = - categoryManagerData.categories().toList(); + final List categoryList = + getLocalCategoryList(categoryManagerData.categories().toList()); return ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, @@ -156,14 +177,14 @@ class SubSpaces extends ConsumerWidget { ); } - Widget _buildCategoriesList(BuildContext context, Category category) { - final entries = category.entries().map((s) => s.toDartString()).toList(); + Widget _buildCategoriesList(BuildContext context, CategoryModelLocal categoryModelLocal) { + final entries = categoryModelLocal.entries; return Card( child: ExpansionTile( initiallyExpanded: true, shape: const Border(), backgroundColor: Theme.of(context).colorScheme.secondaryContainer, - title: CategoryHeaderView(category: category), + title: CategoryHeaderView(categoryModelLocal: categoryModelLocal), children: List.generate( entries.length, (index) => SpaceCard( diff --git a/app/lib/features/spaces/providers/space_list_provider.dart b/app/lib/features/spaces/providers/space_list_provider.dart new file mode 100644 index 000000000000..140fe02a0e22 --- /dev/null +++ b/app/lib/features/spaces/providers/space_list_provider.dart @@ -0,0 +1,21 @@ +import 'package:acter/common/providers/space_providers.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +final subSpacesListProvider = + FutureProvider.family, String>((ref, spaceId) async { + List subSpacesList = []; + + //Get known sub-spaces + final spaceRelationsOverview = + await ref.watch(spaceRelationsOverviewProvider(spaceId).future); + subSpacesList.addAll(spaceRelationsOverview.knownSubspaces); + + //Get more sub-spaces + final relatedSpacesLoader = + await ref.watch(remoteSubspaceRelationsProvider(spaceId).future); + for (var element in relatedSpacesLoader) { + subSpacesList.add(element.roomIdStr()); + } + + return subSpacesList; +}); From 04045cfd76129ed2923bab2d497b2033a455dd6a Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Mon, 16 Sep 2024 19:33:30 +0530 Subject: [PATCH 22/57] Manage actual space list with categories and un-categories data --- .../categories/actions/save_categories.dart | 84 +++++++++++-------- .../categories/draggable_category_list.dart | 9 +- .../categories/utils/category_utils.dart | 37 ++++++++ .../widgets/category_header_view.dart | 14 +++- app/lib/features/spaces/pages/sub_spaces.dart | 73 ++++++++-------- 5 files changed, 144 insertions(+), 73 deletions(-) diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index a056a97f5457..28dc3dace045 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -36,20 +36,22 @@ void saveCategories( //Clear category builder data and Add new categoriesBuilder.clear(); for (int i = 0; i < categoryList.length; i++) { - final newCategoryItem = categoriesManager.newCategoryBuilder(); - //ADD TITLE - newCategoryItem.title(categoryList[i].title); - - //ADD COLOR AND ICON - displayBuilder.color(categoryList[i].color.value); - displayBuilder.icon('acter-icon', categoryList[i].icon.name); - newCategoryItem.display(displayBuilder.build()); - - //ADD ENTRIES - for (int j = 0; j < categoryList[i].entries.length; j++) { - newCategoryItem.addEntry(categoryList[i].entries[j]); + if (categoryList[i].title != 'Un-categorized') { + final newCategoryItem = categoriesManager.newCategoryBuilder(); + //ADD TITLE + newCategoryItem.title(categoryList[i].title); + + //ADD COLOR AND ICON + displayBuilder.color(categoryList[i].color.value); + displayBuilder.icon('acter-icon', categoryList[i].icon.name); + newCategoryItem.display(displayBuilder.build()); + + //ADD ENTRIES + for (int j = 0; j < categoryList[i].entries.length; j++) { + newCategoryItem.addEntry(categoryList[i].entries[j]); + } + categoriesBuilder.add(newCategoryItem.build()); } - categoriesBuilder.add(newCategoryItem.build()); } //Save category builder @@ -73,6 +75,39 @@ void saveCategories( } } +Future clearCategories( + BuildContext context, + WidgetRef ref, + String spaceId, +) async { + // Show loading message + EasyLoading.show(status: L10n.of(context).updatingCategories); + try { + final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); + if (maybeSpace != null) { + final categoriesManager = await maybeSpace.categories('spaces'); + + final newCats = categoriesManager.updateBuilder(); + newCats.clear(); + maybeSpace.setCategories('spaces', newCats); + if (context.mounted) { + EasyLoading.dismiss(); + return; + } + } + } catch (e, s) { + _log.severe('Failed to update categories', e, s); + if (context.mounted) { + EasyLoading.dismiss(); + EasyLoading.showError( + L10n.of(context).updatingCategoriesFailed(e), + duration: const Duration(seconds: 3), + ); + return; + } + } +} + Future addDummyData( BuildContext context, WidgetRef ref, @@ -101,8 +136,6 @@ Future addDummyData( newCat1.display(displayBuilder.build()); //ADD ENTRIES - newCat1.addEntry('!ECGEsoitdTwuBFQlWq:m-1.acter.global'); - newCat1.addEntry('!ETVXYJQaiONyZgsjNE:m-1.acter.global'); newCats.add(newCat1.build()); /// --------(NEW CATEGORY-2)-------- @@ -111,30 +144,13 @@ Future addDummyData( //ADD TITLE newCat2.title('Test Cat - 2'); - //ADD COLOR AND ICON - displayBuilder.color(Colors.green.value); - displayBuilder.icon('acter-icon', ActerIcon.airplay.name); - newCat2.display(displayBuilder.build()); - - //ADD ENTRIES - newCat2.addEntry('!QttcPDfFpCKjwjDLgg:m-1.acter.global'); - newCat2.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat2.build()); - - /// --------(NEW CATEGORY-3)-------- - final newCat3 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat3.title('Test Cat - 3'); - //ADD COLOR AND ICON displayBuilder.color(Colors.blue.value); displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); - newCat3.display(displayBuilder.build()); + newCat2.display(displayBuilder.build()); //ADD ENTRIES - newCat3.addEntry('!rvKjUYxJTzOmesLgut:acter.global'); - newCats.add(newCat3.build()); + newCats.add(newCat2.build()); maybeSpace.setCategories('spaces', newCats); } diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 495b3eef3068..43de92fedbdb 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -4,6 +4,7 @@ import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; +import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -42,8 +43,12 @@ class _DraggableCategoriesListState (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), ).future, ); - categoryList = - getLocalCategoryList(categoriesManager.categories().toList()); + final subSpaceList = + await ref.read(subSpacesListProvider(widget.spaceId).future); + categoryList = getCategorisedSubSpaces( + categoriesManager.categories().toList(), + subSpaceList, + ); setDragAndDropListData(); } diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 14e18e5d3794..885f7367bc73 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -3,6 +3,43 @@ import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; +import 'package:flutter/material.dart'; + +List getCategorisedSubSpaces( + List categoryList, + List subSpaceList, +) { + //CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST + List categoryListLocal = + getLocalCategoryList(categoryList); + + //GET CATEGORIES SPACE IDs + List categoriesSpaceIds = []; + for (var spaceId in subSpaceList) { + for (var categoryItemLocal in categoryListLocal) { + if (categoryItemLocal.entries.contains(spaceId)) { + categoriesSpaceIds.add(spaceId); + } + } + } + + //GET UN-CATEGORIES SPACE IDs + List unCategoriesSpaceIds = subSpaceList; + for (var spaceId in categoriesSpaceIds) { + unCategoriesSpaceIds.remove(spaceId); + } + + //ADD UN-CATEGORIES ITEM + CategoryModelLocal unCategorized = CategoryModelLocal( + entries: unCategoriesSpaceIds, + title: 'Un-categorized', + icon: ActerIcon.list, + color: Colors.blueGrey, + ); + categoryListLocal.add(unCategorized); + + return categoryListLocal; +} List getLocalCategoryList(List categoryList) { List categoryListLocal = []; diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index 0742a435e9dd..0715832d7c0c 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -15,7 +15,9 @@ class CategoryHeaderView extends StatelessWidget { @override Widget build(BuildContext context) { - return _buildCategoryHeader(); + return (categoryModelLocal.title == 'Un-categorized') + ? _buildUnCategoriesHeader(context) + : _buildCategoryHeader(); } Widget _buildCategoryHeader() { @@ -33,4 +35,14 @@ class CategoryHeaderView extends StatelessWidget { ], ); } + + Widget _buildUnCategoriesHeader(BuildContext context) { + return Text( + categoryModelLocal.title, + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: Theme.of(context).disabledColor), + ); + } } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 5f933de5c05c..acbddfa1fbf0 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -7,6 +7,7 @@ import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; +import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -52,6 +53,10 @@ class SubSpaces extends ConsumerWidget { ], ), actions: [ + IconButton( + icon: Icon(PhosphorIcons.x()), + onPressed: () => clearCategories(context, ref, spaceId), + ), IconButton( icon: Icon(PhosphorIcons.plusCircle()), onPressed: () => addDummyData(context, ref, spaceId), @@ -131,56 +136,52 @@ class SubSpaces extends ConsumerWidget { } Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { - final categoryManager = ref.watch( - categoryManagerProvider( - (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), - ), - ); - // final subSpaceList = ref.watch(subSpacesListProvider(spaceId)); - // - // return subSpaceList.when( - // data: (subSpaceListData) { - // return ListView.builder( - // scrollDirection: Axis.vertical, - // shrinkWrap: true, - // itemCount: subSpaceListData.length, - // itemBuilder: (BuildContext context, int index) { - // return SpaceCard(roomId: subSpaceListData[index]); - // }, - // ); - // }, - // error: (e, s) { - // _log.severe('Failed to load the space categories', e, s); - // return Center(child: Text(L10n.of(context).loadingFailed(e))); - // }, - // loading: () => Center(child: Text(L10n.of(context).loading)), - // ); + final subSpaceList = ref.watch(subSpacesListProvider(spaceId)); - return categoryManager.when( - data: (categoryManagerData) { - final List categoryList = - getLocalCategoryList(categoryManagerData.categories().toList()); - return ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: categoryList.length, - itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(context, categoryList[index]); + return subSpaceList.when( + data: (subSpaceListData) { + final categoryManager = ref.watch( + categoryManagerProvider( + (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), + ), + ); + return categoryManager.when( + data: (categoryManagerData) { + final List categoryList = + getCategorisedSubSpaces( + categoryManagerData.categories().toList(), + subSpaceListData, + ); + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(context, categoryList[index]); + }, + ); + }, + error: (e, s) { + _log.severe('Failed to load the space categories', e, s); + return Center(child: Text(L10n.of(context).loadingFailed(e))); }, + loading: () => Center(child: Text(L10n.of(context).loading)), ); }, error: (e, s) { - _log.severe('Failed to load the space categories', e, s); + _log.severe('Failed to load the sub-spaces', e, s); return Center(child: Text(L10n.of(context).loadingFailed(e))); }, loading: () => Center(child: Text(L10n.of(context).loading)), ); } - Widget _buildCategoriesList(BuildContext context, CategoryModelLocal categoryModelLocal) { + Widget _buildCategoriesList( + BuildContext context, CategoryModelLocal categoryModelLocal) { final entries = categoryModelLocal.entries; return Card( child: ExpansionTile( + showTrailingIcon: false, initiallyExpanded: true, shape: const Border(), backgroundColor: Theme.of(context).colorScheme.secondaryContainer, From f64e90510e0636f27cc9d57451adcb192efeb7ef Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Mon, 16 Sep 2024 19:45:26 +0530 Subject: [PATCH 23/57] Fixed lint error --- app/lib/features/spaces/pages/sub_spaces.dart | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index acbddfa1fbf0..76ab0e6192cd 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -177,7 +177,9 @@ class SubSpaces extends ConsumerWidget { } Widget _buildCategoriesList( - BuildContext context, CategoryModelLocal categoryModelLocal) { + BuildContext context, + CategoryModelLocal categoryModelLocal, + ) { final entries = categoryModelLocal.entries; return Card( child: ExpansionTile( From 85617e266cb039b9edc078cc1e207036adf0f1a6 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 15:17:20 +0530 Subject: [PATCH 24/57] Add category flow --- .../categories/actions/add_category.dart | 64 +++++++ .../categories/actions/save_categories.dart | 99 +---------- .../categories/draggable_category_list.dart | 15 +- .../categories/widgets/add_edit_category.dart | 159 ++++++++++++++++++ app/lib/features/spaces/pages/sub_spaces.dart | 9 +- app/lib/l10n/app_en.arb | 4 +- 6 files changed, 243 insertions(+), 107 deletions(-) create mode 100644 app/lib/features/categories/actions/add_category.dart create mode 100644 app/lib/features/categories/widgets/add_edit_category.dart diff --git a/app/lib/features/categories/actions/add_category.dart b/app/lib/features/categories/actions/add_category.dart new file mode 100644 index 000000000000..2ca63139f362 --- /dev/null +++ b/app/lib/features/categories/actions/add_category.dart @@ -0,0 +1,64 @@ +import 'package:acter/common/providers/sdk_provider.dart'; +import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_easyloading/flutter_easyloading.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:logging/logging.dart'; + +final _log = Logger('a3::save_categories'); + +void addCategory( + BuildContext context, + WidgetRef ref, + String spaceId, + CategoriesFor categoriesFor, + String categoryTitle, + Color color, + ActerIcon icon, +) async { + // Show loading message + EasyLoading.show(status: L10n.of(context).addingNewCategory); + try { + //GET REQUIRE DATA FROM PROVIDERS + final categoriesManager = await ref.read( + categoryManagerProvider( + (spaceId: spaceId, categoriesFor: categoriesFor), + ).future, + ); + final sdk = await ref.watch(sdkProvider.future); + final displayBuilder = sdk.api.newDisplayBuilder(); + + //BUILD NEW CATEGORY + final newCategory = categoriesManager.newCategoryBuilder(); + newCategory.title(categoryTitle); + displayBuilder.color(color.value); + displayBuilder.icon('acter-icon', icon.name); + newCategory.display(displayBuilder.build()); + + //SAVE NEW CATEGORY in CATEGORIES BUILDER + final categoriesUpdateBuilder = categoriesManager.updateBuilder(); + categoriesUpdateBuilder.add(newCategory.build()); + + //SAVE UPDATED CATEGORIES BUILDER IN SPACE + final space = await ref.read(spaceProvider(spaceId).future); + space.setCategories(categoriesFor.name, categoriesUpdateBuilder); + + EasyLoading.dismiss(); + if (context.mounted) { + Navigator.pop(context); + } + } catch (e, s) { + _log.severe('Failed to add category', e, s); + if (!context.mounted) { + EasyLoading.dismiss(); + return; + } + EasyLoading.showError( + L10n.of(context).addingNewCategoriesFailed(e), + duration: const Duration(seconds: 3), + ); + } +} diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index 28dc3dace045..d47134856d2f 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -1,6 +1,5 @@ import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:flutter/material.dart'; @@ -73,100 +72,4 @@ void saveCategories( duration: const Duration(seconds: 3), ); } -} - -Future clearCategories( - BuildContext context, - WidgetRef ref, - String spaceId, -) async { - // Show loading message - EasyLoading.show(status: L10n.of(context).updatingCategories); - try { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - final categoriesManager = await maybeSpace.categories('spaces'); - - final newCats = categoriesManager.updateBuilder(); - newCats.clear(); - maybeSpace.setCategories('spaces', newCats); - if (context.mounted) { - EasyLoading.dismiss(); - return; - } - } - } catch (e, s) { - _log.severe('Failed to update categories', e, s); - if (context.mounted) { - EasyLoading.dismiss(); - EasyLoading.showError( - L10n.of(context).updatingCategoriesFailed(e), - duration: const Duration(seconds: 3), - ); - return; - } - } -} - -Future addDummyData( - BuildContext context, - WidgetRef ref, - String spaceId, -) async { - // Show loading message - EasyLoading.show(status: L10n.of(context).updatingCategories); - try { - final maybeSpace = await ref.watch(maybeSpaceProvider(spaceId).future); - if (maybeSpace != null) { - final categoriesManager = await maybeSpace.categories('spaces'); - - final newCats = categoriesManager.updateBuilder(); - newCats.clear(); - final sdk = await ref.watch(sdkProvider.future); - final displayBuilder = sdk.api.newDisplayBuilder(); - - /// --------(NEW CATEGORY-1)-------- - final newCat1 = categoriesManager.newCategoryBuilder(); - //ADD TITLE - newCat1.title('Test Cat - 1'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.red.value); - displayBuilder.icon('acter-icon', ActerIcon.addressBook.name); - newCat1.display(displayBuilder.build()); - - //ADD ENTRIES - newCats.add(newCat1.build()); - - /// --------(NEW CATEGORY-2)-------- - final newCat2 = categoriesManager.newCategoryBuilder(); - - //ADD TITLE - newCat2.title('Test Cat - 2'); - - //ADD COLOR AND ICON - displayBuilder.color(Colors.blue.value); - displayBuilder.icon('acter-icon', ActerIcon.appleLogo.name); - newCat2.display(displayBuilder.build()); - - //ADD ENTRIES - newCats.add(newCat2.build()); - - maybeSpace.setCategories('spaces', newCats); - } - if (context.mounted) { - EasyLoading.dismiss(); - return; - } - } catch (e, s) { - _log.severe('Failed to update categories', e, s); - if (context.mounted) { - EasyLoading.dismiss(); - EasyLoading.showError( - L10n.of(context).updatingCategoriesFailed(e), - duration: const Duration(seconds: 3), - ); - return; - } - } -} +} \ No newline at end of file diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 43de92fedbdb..e8d927b1414d 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -1,8 +1,10 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/features/categories/actions/add_category.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; +import 'package:acter/features/categories/widgets/add_edit_category.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; @@ -137,7 +139,18 @@ class _DraggableCategoriesListState Expanded( child: OutlinedButton( style: buttonStyle, - onPressed: () => Navigator.pop(context), + onPressed: () => showAddEditCategoryBottomSheet( + context: context, + onSave: (title, color, icon) => addCategory( + context, + ref, + widget.spaceId, + widget.categoriesFor, + title, + color, + icon, + ), + ), child: Text(L10n.of(context).createCategory), ), ), diff --git a/app/lib/features/categories/widgets/add_edit_category.dart b/app/lib/features/categories/widgets/add_edit_category.dart new file mode 100644 index 000000000000..46df4fcd055f --- /dev/null +++ b/app/lib/features/categories/widgets/add_edit_category.dart @@ -0,0 +1,159 @@ +import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; +import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; +import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +void showAddEditCategoryBottomSheet({ + required BuildContext context, + String? bottomSheetTitle, + String? title, + Color? color, + ActerIcon? icon, + required Function(String, Color, ActerIcon) onSave, +}) { + showModalBottomSheet( + showDragHandle: true, + useSafeArea: true, + context: context, + isDismissible: true, + isScrollControlled: true, + builder: (context) { + return AddEditCategoryBottomSheet( + bottomSheetTitle: bottomSheetTitle, + title: title, + color: color, + icon: icon, + onSave: onSave, + ); + }, + ); +} + +class AddEditCategoryBottomSheet extends ConsumerStatefulWidget { + final String? bottomSheetTitle; + final String? title; + final Color? color; + final ActerIcon? icon; + final Function(String, Color, ActerIcon) onSave; + + const AddEditCategoryBottomSheet({ + super.key, + this.bottomSheetTitle, + this.title, + this.color, + this.icon, + required this.onSave, + }); + + @override + ConsumerState createState() => + _AddEditCategoryBottomSheet(); +} + +class _AddEditCategoryBottomSheet + extends ConsumerState { + final _formKey = GlobalKey(); + final _titleController = TextEditingController(); + late Color color; + late ActerIcon icon; + + @override + void initState() { + super.initState(); + _titleController.text = widget.title ?? ''; + color = widget.color ?? Colors.blueGrey; + icon = widget.icon ?? ActerIcon.list; + } + + @override + Widget build(BuildContext context) { + return Padding( + padding: MediaQuery.of(context).viewInsets, + child: Form( + key: _formKey, + autovalidateMode: AutovalidateMode.onUserInteraction, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 14), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + widget.bottomSheetTitle ?? L10n.of(context).edit, + textAlign: TextAlign.center, + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 40), + ActerIconWidget( + color: color, + icon: icon, + onIconSelection: (color, icon) { + setState(() { + this.color = color; + this.icon = icon; + }); + }, + ), + const SizedBox(height: 40), + _widgetTitleField(), + const SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + OutlinedButton( + onPressed: () => Navigator.pop(context), + child: Text(L10n.of(context).cancel), + ), + const SizedBox(width: 20), + ActerPrimaryActionButton( + onPressed: () { + if (!_formKey.currentState!.validate()) return; + + // no changes to submit + if (_titleController.text.trim() == + widget.title?.trim() && + color == widget.color && + icon == widget.icon) { + Navigator.pop(context); + return; + } + + // Need to update change of tile + widget.onSave( + _titleController.text.trim(), + color, + icon, + ); + Navigator.pop(context); + }, + child: Text(L10n.of(context).save), + ), + ], + ), + const SizedBox(height: 20), + ], + ), + ), + ), + ); + } + + Widget _widgetTitleField() { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(L10n.of(context).title), + const SizedBox(height: 6), + TextFormField( + keyboardType: TextInputType.text, + textInputAction: TextInputAction.next, + controller: _titleController, + autofocus: true, + minLines: 1, + maxLines: 1, + ), + ], + ); + } +} diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 76ab0e6192cd..e65384f80118 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,7 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/draggable_category_list.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; @@ -54,12 +53,8 @@ class SubSpaces extends ConsumerWidget { ), actions: [ IconButton( - icon: Icon(PhosphorIcons.x()), - onPressed: () => clearCategories(context, ref, spaceId), - ), - IconButton( - icon: Icon(PhosphorIcons.plusCircle()), - onPressed: () => addDummyData(context, ref, spaceId), + icon: Icon(PhosphorIcons.arrowsClockwise()), + onPressed: () => ref.invalidate(subSpacesListProvider), ), if (canLinkSpace) _buildMenuOptions(context), ], diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 437a3126d812..8c935b4441fb 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2175,7 +2175,7 @@ "colonCharacter": " : ", "@colonCharacter": {}, "andSeparator": " and ", - "andNMore":", and {count} more", + "andNMore": ", and {count} more", "errorLoadingSpaces": "Error loading spaces: {error}", "@errorLoadingSpaces": {}, "eventNoLongerAvailable": "Event no longer available", @@ -2191,6 +2191,8 @@ "organized": "Organized", "updatingCategories": "Updating categories", "updatingCategoriesFailed": "Updating categories failed {error}", + "addingNewCategory": "Adding new category", + "addingNewCategoriesFailed": "Adding new category failed {error}", "action": "Action", "@action": {} } From cb7008945986750fe7826b0ebf35675320af4746 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 16:18:52 +0530 Subject: [PATCH 25/57] Menu options to category and general structure changes in space listing --- app/lib/common/widgets/spaces/space_card.dart | 6 ++ .../spaces/space_with_profile_card.dart | 21 +++- .../categories/draggable_category_list.dart | 98 +++++++++---------- .../widgets/category_header_view.dart | 83 ++++++++++++---- app/lib/features/spaces/pages/sub_spaces.dart | 5 +- app/lib/l10n/app_en.arb | 2 + 6 files changed, 139 insertions(+), 76 deletions(-) diff --git a/app/lib/common/widgets/spaces/space_card.dart b/app/lib/common/widgets/spaces/space_card.dart index eda19f2f0231..04c499540bc8 100644 --- a/app/lib/common/widgets/spaces/space_card.dart +++ b/app/lib/common/widgets/spaces/space_card.dart @@ -72,6 +72,9 @@ class SpaceCard extends ConsumerWidget { /// the default border. final bool withBorder; + /// Custom Leading Widget + final Widget? leading; + /// Custom Trailing Widget final Widget? trailing; @@ -106,6 +109,7 @@ class SpaceCard extends ConsumerWidget { this.showParents = true, this.showSuggestedMark = false, this.showVisibilityMark = false, + this.leading, this.trailing, }); @@ -127,6 +131,7 @@ class SpaceCard extends ConsumerWidget { this.showParents = false, this.showSuggestedMark = false, this.showVisibilityMark = false, + this.leading, this.trailing, }); @@ -149,6 +154,7 @@ class SpaceCard extends ConsumerWidget { showParents: showParents, showSuggestedMark: showSuggestedMark, showVisibilityMark: showVisibilityMark, + leading: leading, trailing: trailing, ); } diff --git a/app/lib/common/widgets/spaces/space_with_profile_card.dart b/app/lib/common/widgets/spaces/space_with_profile_card.dart index a106b2355d7a..4330747e1bd4 100644 --- a/app/lib/common/widgets/spaces/space_with_profile_card.dart +++ b/app/lib/common/widgets/spaces/space_with_profile_card.dart @@ -9,6 +9,7 @@ class SpaceWithAvatarInfoCard extends StatelessWidget { final AvatarInfo avatarInfo; final List? parents; final Widget? subtitle; + final Widget? leading; final Widget? trailing; final double avatarSize; @@ -85,6 +86,7 @@ class SpaceWithAvatarInfoCard extends StatelessWidget { required this.avatarInfo, this.parents, this.subtitle, + this.leading, this.trailing, this.onTap, this.onLongPress, @@ -129,9 +131,22 @@ class SpaceWithAvatarInfoCard extends StatelessWidget { titleTextStyle: titleTextStyle, subtitleTextStyle: subtitleTextStyle, leadingAndTrailingTextStyle: leadingAndTrailingTextStyle, - title: Text(title, overflow: TextOverflow.ellipsis), - subtitle: buildSubtitle(context), - leading: avatar, + title: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + avatar, + const SizedBox(width: 12), + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, overflow: TextOverflow.ellipsis), + buildSubtitle(context) ?? const SizedBox.shrink(), + ], + ), + ], + ), + leading: leading, trailing: trailing, ), ); diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index e8d927b1414d..5c7f6a9dabf5 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -57,12 +57,12 @@ class _DraggableCategoriesListState void setDragAndDropListData() { dragAndDropList = List.generate(categoryList.length, (indexCategory) { return DragAndDropList( - header: Padding( - padding: const EdgeInsets.all(14), - child: CategoryHeaderView( - categoryModelLocal: categoryList[indexCategory], - isShowDragHandle: true, - ), + canDrag: categoryList[indexCategory].title != 'Un-categorized', + header: CategoryHeaderView( + categoryModelLocal: categoryList[indexCategory], + isShowDragHandle: true, + headerBackgroundColor: + Theme.of(context).unselectedWidgetColor.withOpacity(0.7), ), children: List.generate( categoryList[indexCategory].entries.length, @@ -71,7 +71,7 @@ class _DraggableCategoriesListState roomId: categoryList[indexCategory].entries[indexEntry].toString(), margin: const EdgeInsets.symmetric(vertical: 6), - trailing: Icon(PhosphorIcons.dotsSixVertical()), + leading: Icon(PhosphorIcons.dotsSixVertical()), ), ), ), @@ -84,17 +84,17 @@ class _DraggableCategoriesListState Widget build(BuildContext context) { return SafeArea( child: Container( - color: Theme.of(context).colorScheme.primaryContainer, - padding: const EdgeInsets.all(16), + color: Theme.of(context).colorScheme.secondaryContainer, + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 16), child: Column( children: [ _buildAppBarUI(), const Divider(endIndent: 0, indent: 0), Expanded( - child: Stack( + child: Column( children: [ - _buildSubSpacesUIWithDrag(), - Positioned.fill(child: _buildActionButtons()), + Expanded(child: _buildSubSpacesUIWithDrag()), + _buildActionButtons(), ], ), ), @@ -124,52 +124,48 @@ class _DraggableCategoriesListState final buttonStyle = OutlinedButton.styleFrom( backgroundColor: Theme.of(context).primaryColor, ); - return Align( - alignment: Alignment.bottomCenter, - child: Container( - padding: const EdgeInsets.all(18), - margin: const EdgeInsets.symmetric(horizontal: 8, vertical: 30), - decoration: BoxDecoration( - color: Theme.of(context).primaryColor.withOpacity(0.8), - borderRadius: const BorderRadius.all(Radius.circular(16)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () => showAddEditCategoryBottomSheet( - context: context, - onSave: (title, color, icon) => addCategory( - context, - ref, - widget.spaceId, - widget.categoriesFor, - title, - color, - icon, - ), - ), - child: Text(L10n.of(context).createCategory), - ), - ), - const SizedBox(width: 30), - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () => saveCategories( + return Container( + padding: const EdgeInsets.all(18), + decoration: BoxDecoration( + color: Theme.of(context).primaryColor.withOpacity(0.8), + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () => showAddEditCategoryBottomSheet( + context: context, + onSave: (title, color, icon) => addCategory( context, ref, widget.spaceId, widget.categoriesFor, - categoryList, + title, + color, + icon, ), - child: Text(L10n.of(context).save), ), + child: Text(L10n.of(context).createCategory), ), - ], - ), + ), + const SizedBox(width: 30), + Expanded( + child: OutlinedButton( + style: buttonStyle, + onPressed: () => saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ), + child: Text(L10n.of(context).save), + ), + ), + ], ), ); } diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index 0715832d7c0c..94102853d550 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -2,47 +2,90 @@ import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:flutter/material.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; class CategoryHeaderView extends StatelessWidget { final CategoryModelLocal categoryModelLocal; + final Color? headerBackgroundColor; final bool isShowDragHandle; const CategoryHeaderView({ super.key, required this.categoryModelLocal, this.isShowDragHandle = false, + this.headerBackgroundColor, }); @override Widget build(BuildContext context) { return (categoryModelLocal.title == 'Un-categorized') ? _buildUnCategoriesHeader(context) - : _buildCategoryHeader(); + : _buildCategoryHeader(context); } - Widget _buildCategoryHeader() { - return Row( - children: [ - ActerIconWidget( - iconSize: 24, - color: categoryModelLocal.color, - icon: categoryModelLocal.icon, - ), - const SizedBox(width: 6), - Text(categoryModelLocal.title), - const Spacer(), - if (isShowDragHandle) Icon(PhosphorIcons.dotsSixVertical()), - ], + Widget _buildCategoryHeader(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: headerBackgroundColor, + borderRadius: const BorderRadius.all(Radius.circular(16)), + ), + child: Row( + children: [ + if (isShowDragHandle) Icon(PhosphorIcons.dotsSixVertical()), + ActerIconWidget( + iconSize: 24, + color: categoryModelLocal.color, + icon: categoryModelLocal.icon, + ), + const SizedBox(width: 6), + Text(categoryModelLocal.title), + const Spacer(), + _buildMenuOptions(context), + ], + ), ); } Widget _buildUnCategoriesHeader(BuildContext context) { - return Text( - categoryModelLocal.title, - style: Theme.of(context) - .textTheme - .titleSmall! - .copyWith(color: Theme.of(context).disabledColor), + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 8), + child: Text( + categoryModelLocal.title, + style: Theme.of(context) + .textTheme + .titleSmall! + .copyWith(color: Theme.of(context).disabledColor), + ), + ); + } + + Widget _buildMenuOptions(BuildContext context) { + return PopupMenuButton( + icon: Icon(PhosphorIcons.dotsThreeVertical()), + iconSize: 28, + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + onTap: () {}, + child: Row( + children: [ + Icon(PhosphorIcons.pencil()), + const SizedBox(width: 6), + Text(L10n.of(context).editCategory), + ], + ), + ), + PopupMenuItem( + onTap: () {}, + child: Row( + children: [ + Icon(PhosphorIcons.trash()), + const SizedBox(width: 6), + Text(L10n.of(context).deleteCategory), + ], + ), + ), + ], ); } } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index e65384f80118..99dc9670537d 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -178,16 +178,17 @@ class SubSpaces extends ConsumerWidget { final entries = categoryModelLocal.entries; return Card( child: ExpansionTile( + tilePadding: EdgeInsets.zero, showTrailingIcon: false, initiallyExpanded: true, shape: const Border(), - backgroundColor: Theme.of(context).colorScheme.secondaryContainer, + collapsedBackgroundColor: Colors.transparent, title: CategoryHeaderView(categoryModelLocal: categoryModelLocal), children: List.generate( entries.length, (index) => SpaceCard( roomId: entries[index], - margin: const EdgeInsets.symmetric(vertical: 6), + margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), ), ), ), diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 8c935b4441fb..36bbe47f35e5 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2194,5 +2194,7 @@ "addingNewCategory": "Adding new category", "addingNewCategoriesFailed": "Adding new category failed {error}", "action": "Action", + "editCategory": "Edit Category", + "deleteCategory": "Delete Category", "@action": {} } From ef0c96085653e8bf3fd59869f3e2f4e9b2e518f1 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 16:21:31 +0530 Subject: [PATCH 26/57] Minor UI Change --- app/lib/features/categories/widgets/category_header_view.dart | 2 +- app/lib/features/spaces/pages/sub_spaces.dart | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index 94102853d550..a42ad41e9c4d 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -41,7 +41,7 @@ class CategoryHeaderView extends StatelessWidget { const SizedBox(width: 6), Text(categoryModelLocal.title), const Spacer(), - _buildMenuOptions(context), + if (isShowDragHandle) _buildMenuOptions(context), ], ), ); diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 99dc9670537d..9e5f6fdbe7fb 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -178,8 +178,7 @@ class SubSpaces extends ConsumerWidget { final entries = categoryModelLocal.entries; return Card( child: ExpansionTile( - tilePadding: EdgeInsets.zero, - showTrailingIcon: false, + tilePadding: const EdgeInsets.only(right: 16), initiallyExpanded: true, shape: const Border(), collapsedBackgroundColor: Colors.transparent, From f5a27d48db8b3ea7d839a7601a3b0455c1558e2c Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 16:53:15 +0530 Subject: [PATCH 27/57] Manage add and delete category with local state --- .../categories/actions/save_categories.dart | 7 +-- .../categories/draggable_category_list.dart | 52 +++++++++++++------ .../widgets/category_header_view.dart | 4 +- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index d47134856d2f..252631684e3c 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -10,7 +10,7 @@ import 'package:logging/logging.dart'; final _log = Logger('a3::save_categories'); -void saveCategories( +Future saveCategories( BuildContext context, WidgetRef ref, String spaceId, @@ -58,9 +58,6 @@ void saveCategories( space.setCategories(categoriesFor.name, categoriesBuilder); EasyLoading.dismiss(); - if (context.mounted) { - Navigator.pop(context); - } } catch (e, s) { _log.severe('Failed to save categories', e, s); if (!context.mounted) { @@ -72,4 +69,4 @@ void saveCategories( duration: const Duration(seconds: 3), ); } -} \ No newline at end of file +} diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/draggable_category_list.dart index 5c7f6a9dabf5..2e190dcd801e 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/draggable_category_list.dart @@ -1,5 +1,4 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter/features/categories/actions/add_category.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; @@ -63,6 +62,17 @@ class _DraggableCategoriesListState isShowDragHandle: true, headerBackgroundColor: Theme.of(context).unselectedWidgetColor.withOpacity(0.7), + onClickDeleteCategory: () async { + categoryList.removeAt(indexCategory); + await saveCategories( + context, + ref, + widget.spaceId, + CategoriesFor.spaces, + categoryList, + ); + setDragAndDropListData(); + }, ), children: List.generate( categoryList[indexCategory].entries.length, @@ -138,15 +148,20 @@ class _DraggableCategoriesListState style: buttonStyle, onPressed: () => showAddEditCategoryBottomSheet( context: context, - onSave: (title, color, icon) => addCategory( - context, - ref, - widget.spaceId, - widget.categoriesFor, - title, - color, - icon, - ), + onSave: (title, color, icon) { + setState(() { + categoryList.insert( + categoryList.length - 1, + CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: [], + ), + ); + }); + setDragAndDropListData(); + }, ), child: Text(L10n.of(context).createCategory), ), @@ -155,13 +170,16 @@ class _DraggableCategoriesListState Expanded( child: OutlinedButton( style: buttonStyle, - onPressed: () => saveCategories( - context, - ref, - widget.spaceId, - widget.categoriesFor, - categoryList, - ), + onPressed: () async { + await saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ); + if (context.mounted) Navigator.pop(context); + }, child: Text(L10n.of(context).save), ), ), diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index a42ad41e9c4d..3d67c1122b22 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -8,12 +8,14 @@ class CategoryHeaderView extends StatelessWidget { final CategoryModelLocal categoryModelLocal; final Color? headerBackgroundColor; final bool isShowDragHandle; + final Function()? onClickDeleteCategory; const CategoryHeaderView({ super.key, required this.categoryModelLocal, this.isShowDragHandle = false, this.headerBackgroundColor, + this.onClickDeleteCategory, }); @override @@ -76,7 +78,7 @@ class CategoryHeaderView extends StatelessWidget { ), ), PopupMenuItem( - onTap: () {}, + onTap: () => onClickDeleteCategory!=null?onClickDeleteCategory!():null, child: Row( children: [ Icon(PhosphorIcons.trash()), From ed068019336e71851a4e0b6faf90c05f1518ea15 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 17:30:19 +0530 Subject: [PATCH 28/57] Moved Organized category as separate screen --- app/lib/common/utils/routes.dart | 2 + ...ry_list.dart => organized_categories.dart} | 133 +++++++----------- .../categories/utils/category_utils.dart | 13 +- app/lib/features/spaces/pages/sub_spaces.dart | 17 +-- .../shell_routers/home_shell_router.dart | 17 +++ 5 files changed, 86 insertions(+), 96 deletions(-) rename app/lib/features/categories/{draggable_category_list.dart => organized_categories.dart} (62%) diff --git a/app/lib/common/utils/routes.dart b/app/lib/common/utils/routes.dart index 31cb2557d0c4..b3a7a4d026d9 100644 --- a/app/lib/common/utils/routes.dart +++ b/app/lib/common/utils/routes.dart @@ -67,6 +67,7 @@ enum Routes { space('/:spaceId([!#][^/]+)'), // !spaceId, #spaceName spaceRelatedSpaces('/:spaceId([!#][^/]+)/spaces'), subSpaces('/:spaceId([!#][^/]+)/subSpaces'), + organizedCategories('/organizedCategories/:spaceId([^/]+)/:categoriesFor([^/]+)'), spaceMembers('/:spaceId([!#][^/]+)/members'), spacePins('/:spaceId([!#][^/]+)/pins'), spaceEvents('/:spaceId([!#][^/]+)/events'), @@ -113,5 +114,6 @@ enum Routes { fatalFail('/error'); const Routes(this.route); + final String route; } diff --git a/app/lib/features/categories/draggable_category_list.dart b/app/lib/features/categories/organized_categories.dart similarity index 62% rename from app/lib/features/categories/draggable_category_list.dart rename to app/lib/features/categories/organized_categories.dart index 2e190dcd801e..29d97ec9ae2c 100644 --- a/app/lib/features/categories/draggable_category_list.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -1,3 +1,4 @@ +import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; @@ -12,23 +13,22 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; -class DraggableCategoryList extends ConsumerStatefulWidget { +class OrganizedCategories extends ConsumerStatefulWidget { final String spaceId; final CategoriesFor categoriesFor; - const DraggableCategoryList({ + const OrganizedCategories({ super.key, required this.spaceId, required this.categoriesFor, }); @override - ConsumerState createState() => + ConsumerState createState() => _DraggableCategoriesListState(); } -class _DraggableCategoriesListState - extends ConsumerState { +class _DraggableCategoriesListState extends ConsumerState { List? dragAndDropList; late List categoryList; @@ -92,98 +92,67 @@ class _DraggableCategoriesListState @override Widget build(BuildContext context) { - return SafeArea( - child: Container( - color: Theme.of(context).colorScheme.secondaryContainer, + return Scaffold( + appBar: _buildAppBarUI(), + body: Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 16), child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - _buildAppBarUI(), - const Divider(endIndent: 0, indent: 0), - Expanded( - child: Column( - children: [ - Expanded(child: _buildSubSpacesUIWithDrag()), - _buildActionButtons(), - ], - ), - ), + Expanded(child: _buildSubSpacesUIWithDrag()), + _buildSaveCategoriesButton(), ], ), ), ); } - Widget _buildAppBarUI() { - return Row( - children: [ - Text( - L10n.of(context).organized, - style: Theme.of(context).textTheme.titleLarge, - ), - const Spacer(), + AppBar _buildAppBarUI() { + return AppBar( + title: Text( + L10n.of(context).organized, + style: Theme.of(context).textTheme.titleLarge, + ), + actions: [ IconButton( - icon: Icon(PhosphorIcons.x()), - onPressed: () => Navigator.pop(context), + icon: Icon(PhosphorIcons.plus()), + onPressed: () => showAddEditCategoryBottomSheet( + context: context, + onSave: (title, color, icon) { + setState(() { + categoryList.insert( + categoryList.length - 1, + CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: [], + ), + ); + }); + setDragAndDropListData(); + }, + ), ), ], ); } - Widget _buildActionButtons() { - final buttonStyle = OutlinedButton.styleFrom( - backgroundColor: Theme.of(context).primaryColor, - ); - return Container( - padding: const EdgeInsets.all(18), - decoration: BoxDecoration( - color: Theme.of(context).primaryColor.withOpacity(0.8), - borderRadius: const BorderRadius.all(Radius.circular(16)), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () => showAddEditCategoryBottomSheet( - context: context, - onSave: (title, color, icon) { - setState(() { - categoryList.insert( - categoryList.length - 1, - CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: [], - ), - ); - }); - setDragAndDropListData(); - }, - ), - child: Text(L10n.of(context).createCategory), - ), - ), - const SizedBox(width: 30), - Expanded( - child: OutlinedButton( - style: buttonStyle, - onPressed: () async { - await saveCategories( - context, - ref, - widget.spaceId, - widget.categoriesFor, - categoryList, - ); - if (context.mounted) Navigator.pop(context); - }, - child: Text(L10n.of(context).save), - ), - ), - ], + Widget _buildSaveCategoriesButton() { + return Padding( + padding: const EdgeInsets.all(8.0), + child: ActerPrimaryActionButton( + onPressed: () async { + await saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ); + if (context.mounted) Navigator.pop(context); + }, + child: Text(L10n.of(context).save), ), ); } diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 885f7367bc73..0f96a7cde043 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -1,19 +1,24 @@ import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; import 'package:acter/common/widgets/acter_icon_picker/model/color_data.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter/material.dart'; +CategoriesFor getCategoryEnumFromName(String name) { + return CategoriesFor.values.firstWhere((v) => v.name == name); +} + List getCategorisedSubSpaces( List categoryList, List subSpaceList, ) { - //CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST +//CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST List categoryListLocal = getLocalCategoryList(categoryList); - //GET CATEGORIES SPACE IDs +//GET CATEGORIES SPACE IDs List categoriesSpaceIds = []; for (var spaceId in subSpaceList) { for (var categoryItemLocal in categoryListLocal) { @@ -23,13 +28,13 @@ List getCategorisedSubSpaces( } } - //GET UN-CATEGORIES SPACE IDs +//GET UN-CATEGORIES SPACE IDs List unCategoriesSpaceIds = subSpaceList; for (var spaceId in categoriesSpaceIds) { unCategoriesSpaceIds.remove(spaceId); } - //ADD UN-CATEGORIES ITEM +//ADD UN-CATEGORIES ITEM CategoryModelLocal unCategorized = CategoryModelLocal( entries: unCategoriesSpaceIds, title: 'Un-categorized', diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 9e5f6fdbe7fb..82d0d840be96 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,7 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; -import 'package:acter/features/categories/draggable_category_list.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; @@ -109,15 +108,13 @@ class SubSpaces extends ConsumerWidget { ), ), PopupMenuItem( - onTap: () { - showDialog( - context: context, - builder: (context) => DraggableCategoryList( - spaceId: spaceId, - categoriesFor: CategoriesFor.spaces, - ), - ); - }, + onTap: () => context.pushNamed( + Routes.organizedCategories.name, + pathParameters: { + 'spaceId': spaceId, + 'categoriesFor': CategoriesFor.spaces.name, + }, + ), child: Row( children: [ Icon(PhosphorIcons.dotsSixVertical()), diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 3497720af2cc..79f5256b91d3 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -1,5 +1,7 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/with_sidebar.dart'; +import 'package:acter/features/categories/organized_categories.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/events/pages/create_event_page.dart'; import 'package:acter/features/events/pages/event_list_page.dart'; import 'package:acter/features/invite_members/pages/invite_individual_users.dart'; @@ -238,6 +240,21 @@ final homeShellRoutes = [ ); }, ), + GoRoute( + name: Routes.organizedCategories.name, + path: Routes.organizedCategories.route, + redirect: authGuardRedirect, + pageBuilder: (context, state) { + return NoTransitionPage( + key: state.pageKey, + child: OrganizedCategories( + spaceId: state.pathParameters['spaceId']!, + categoriesFor: + getCategoryEnumFromName(state.pathParameters['categoriesFor']!), + ), + ); + }, + ), GoRoute( name: Routes.spaceMembers.name, path: Routes.spaceMembers.route, From 14bc6249edc34dedee6eb48b3014621d21c01cce Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 17:33:05 +0530 Subject: [PATCH 29/57] Added relevant title --- .../categories/organized_categories.dart | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index 29d97ec9ae2c..14d0b91d4de2 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -1,3 +1,4 @@ +import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; @@ -108,10 +109,22 @@ class _DraggableCategoriesListState extends ConsumerState { } AppBar _buildAppBarUI() { + final spaceName = + ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; return AppBar( - title: Text( - L10n.of(context).organized, - style: Theme.of(context).textTheme.titleLarge, + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + L10n.of(context).organized, + style: Theme.of(context).textTheme.titleLarge, + ), + Text( + '(${widget.categoriesFor.name} in $spaceName)', + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelLarge, + ), + ], ), actions: [ IconButton( From 07e5af2e4261e639d6d3b1e7f691b0cc75069ade Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 19:24:46 +0530 Subject: [PATCH 30/57] Edit category draft work --- .../categories/organized_categories.dart | 17 ++++++++++++++++- .../widgets/category_header_view.dart | 8 ++++++-- 2 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index 14d0b91d4de2..d4bfb4f23b1d 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -63,6 +63,21 @@ class _DraggableCategoriesListState extends ConsumerState { isShowDragHandle: true, headerBackgroundColor: Theme.of(context).unselectedWidgetColor.withOpacity(0.7), + onClickEditCategory: () async { + showAddEditCategoryBottomSheet( + context: context, + onSave: (title, color, icon) { + CategoryModelLocal categoryModelLocal = CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: categoryList[indexCategory].entries, + ); + categoryList[indexCategory] = categoryModelLocal; + setDragAndDropList(); + }, + ); + }, onClickDeleteCategory: () async { categoryList.removeAt(indexCategory); await saveCategories( @@ -72,7 +87,7 @@ class _DraggableCategoriesListState extends ConsumerState { CategoriesFor.spaces, categoryList, ); - setDragAndDropListData(); + setDragAndDropList(); }, ), children: List.generate( diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index 3d67c1122b22..56b9af0a9787 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -8,6 +8,7 @@ class CategoryHeaderView extends StatelessWidget { final CategoryModelLocal categoryModelLocal; final Color? headerBackgroundColor; final bool isShowDragHandle; + final Function()? onClickEditCategory; final Function()? onClickDeleteCategory; const CategoryHeaderView({ @@ -15,6 +16,7 @@ class CategoryHeaderView extends StatelessWidget { required this.categoryModelLocal, this.isShowDragHandle = false, this.headerBackgroundColor, + this.onClickEditCategory, this.onClickDeleteCategory, }); @@ -68,7 +70,8 @@ class CategoryHeaderView extends StatelessWidget { iconSize: 28, itemBuilder: (BuildContext context) => [ PopupMenuItem( - onTap: () {}, + onTap: () => + onClickEditCategory != null ? onClickEditCategory!() : null, child: Row( children: [ Icon(PhosphorIcons.pencil()), @@ -78,7 +81,8 @@ class CategoryHeaderView extends StatelessWidget { ), ), PopupMenuItem( - onTap: () => onClickDeleteCategory!=null?onClickDeleteCategory!():null, + onTap: () => + onClickDeleteCategory != null ? onClickDeleteCategory!() : null, child: Row( children: [ Icon(PhosphorIcons.trash()), From 808749ca2b0356c4e34d7b71ca91b316a34d3919 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 19:26:52 +0530 Subject: [PATCH 31/57] Edit category draft work --- app/lib/features/categories/organized_categories.dart | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index d4bfb4f23b1d..33a7efbb3293 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -74,7 +74,7 @@ class _DraggableCategoriesListState extends ConsumerState { entries: categoryList[indexCategory].entries, ); categoryList[indexCategory] = categoryModelLocal; - setDragAndDropList(); + setDragAndDropListData(); }, ); }, @@ -87,7 +87,7 @@ class _DraggableCategoriesListState extends ConsumerState { CategoriesFor.spaces, categoryList, ); - setDragAndDropList(); + setDragAndDropListData(); }, ), children: List.generate( From 61d0663bfa7aff5c108e5f733de325799fb1c759 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 19:30:35 +0530 Subject: [PATCH 32/57] Edit category --- .../categories/organized_categories.dart | 68 ++++++++++--------- 1 file changed, 37 insertions(+), 31 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index 33a7efbb3293..b11eda7b2386 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -58,37 +58,43 @@ class _DraggableCategoriesListState extends ConsumerState { dragAndDropList = List.generate(categoryList.length, (indexCategory) { return DragAndDropList( canDrag: categoryList[indexCategory].title != 'Un-categorized', - header: CategoryHeaderView( - categoryModelLocal: categoryList[indexCategory], - isShowDragHandle: true, - headerBackgroundColor: - Theme.of(context).unselectedWidgetColor.withOpacity(0.7), - onClickEditCategory: () async { - showAddEditCategoryBottomSheet( - context: context, - onSave: (title, color, icon) { - CategoryModelLocal categoryModelLocal = CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: categoryList[indexCategory].entries, - ); - categoryList[indexCategory] = categoryModelLocal; - setDragAndDropListData(); - }, - ); - }, - onClickDeleteCategory: () async { - categoryList.removeAt(indexCategory); - await saveCategories( - context, - ref, - widget.spaceId, - CategoriesFor.spaces, - categoryList, - ); - setDragAndDropListData(); - }, + header: Padding( + padding: const EdgeInsets.only(top: 18, bottom: 8), + child: CategoryHeaderView( + categoryModelLocal: categoryList[indexCategory], + isShowDragHandle: true, + headerBackgroundColor: + Theme.of(context).unselectedWidgetColor.withOpacity(0.7), + onClickEditCategory: () async { + showAddEditCategoryBottomSheet( + context: context, + title: categoryList[indexCategory].title, + color: categoryList[indexCategory].color, + icon: categoryList[indexCategory].icon, + onSave: (title, color, icon) { + CategoryModelLocal categoryModelLocal = CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: categoryList[indexCategory].entries, + ); + categoryList[indexCategory] = categoryModelLocal; + setDragAndDropListData(); + }, + ); + }, + onClickDeleteCategory: () async { + categoryList.removeAt(indexCategory); + await saveCategories( + context, + ref, + widget.spaceId, + CategoriesFor.spaces, + categoryList, + ); + setDragAndDropListData(); + }, + ), ), children: List.generate( categoryList[indexCategory].entries.length, From bb86ef26ee05cdd763f4bbbb33f68274fdaadc18 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 19:40:40 +0530 Subject: [PATCH 33/57] Minor wording corrections --- app/lib/features/categories/organized_categories.dart | 1 + app/lib/features/categories/widgets/add_edit_category.dart | 2 +- app/lib/l10n/app_en.arb | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index b11eda7b2386..623d9d3066ab 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -152,6 +152,7 @@ class _DraggableCategoriesListState extends ConsumerState { icon: Icon(PhosphorIcons.plus()), onPressed: () => showAddEditCategoryBottomSheet( context: context, + bottomSheetTitle: L10n.of(context).addCategory, onSave: (title, color, icon) { setState(() { categoryList.insert( diff --git a/app/lib/features/categories/widgets/add_edit_category.dart b/app/lib/features/categories/widgets/add_edit_category.dart index 46df4fcd055f..4adfe1a39a30 100644 --- a/app/lib/features/categories/widgets/add_edit_category.dart +++ b/app/lib/features/categories/widgets/add_edit_category.dart @@ -80,7 +80,7 @@ class _AddEditCategoryBottomSheet mainAxisSize: MainAxisSize.min, children: [ Text( - widget.bottomSheetTitle ?? L10n.of(context).edit, + widget.bottomSheetTitle ?? L10n.of(context).editCategory, textAlign: TextAlign.center, style: Theme.of(context).textTheme.titleMedium, ), diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 36bbe47f35e5..dfc73c77c9df 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2194,6 +2194,7 @@ "addingNewCategory": "Adding new category", "addingNewCategoriesFailed": "Adding new category failed {error}", "action": "Action", + "addCategory": "Add Category", "editCategory": "Edit Category", "deleteCategory": "Delete Category", "@action": {} From 0da2c3585f3a479836c2da54f06c5d468fbf273a Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Tue, 17 Sep 2024 19:47:04 +0530 Subject: [PATCH 34/57] Don't show category which don't have any entries --- .../categories/utils/category_utils.dart | 17 +++++++++++++++++ app/lib/features/spaces/pages/sub_spaces.dart | 2 +- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 0f96a7cde043..023625638511 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -10,6 +10,23 @@ CategoriesFor getCategoryEnumFromName(String name) { return CategoriesFor.values.firstWhere((v) => v.name == name); } +List getCategorisedSubSpacesWithoutEmptyList( + List categoryList, + List subSpaceList, +) { +//CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST + List categoryListLocal = + getCategorisedSubSpaces(categoryList, subSpaceList); + + List categoryListLocalWithoutEmptyEntries = []; + for (var categoryListLocal in categoryListLocal) { + if (categoryListLocal.entries.isNotEmpty) { + categoryListLocalWithoutEmptyEntries.add(categoryListLocal); + } + } + return categoryListLocalWithoutEmptyEntries; +} + List getCategorisedSubSpaces( List categoryList, List subSpaceList, diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 82d0d840be96..e367a4a7736f 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -140,7 +140,7 @@ class SubSpaces extends ConsumerWidget { return categoryManager.when( data: (categoryManagerData) { final List categoryList = - getCategorisedSubSpaces( + getCategorisedSubSpacesWithoutEmptyList( categoryManagerData.categories().toList(), subSpaceListData, ); From cb3d15c173f4e9e0a219e137b8e430df1f08b64a Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 08:37:43 +0530 Subject: [PATCH 35/57] Minor fixes --- .../widgets/spaces/space_with_profile_card.dart | 16 +++++++++------- app/lib/features/spaces/pages/sub_spaces.dart | 2 ++ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/app/lib/common/widgets/spaces/space_with_profile_card.dart b/app/lib/common/widgets/spaces/space_with_profile_card.dart index 4330747e1bd4..c7527a8e2070 100644 --- a/app/lib/common/widgets/spaces/space_with_profile_card.dart +++ b/app/lib/common/widgets/spaces/space_with_profile_card.dart @@ -136,13 +136,15 @@ class SpaceWithAvatarInfoCard extends StatelessWidget { children: [ avatar, const SizedBox(width: 12), - Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(title, overflow: TextOverflow.ellipsis), - buildSubtitle(context) ?? const SizedBox.shrink(), - ], + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, overflow: TextOverflow.ellipsis), + buildSubtitle(context) ?? const SizedBox.shrink(), + ], + ), ), ], ), diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index e367a4a7736f..e6668841eb81 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -184,6 +184,8 @@ class SubSpaces extends ConsumerWidget { entries.length, (index) => SpaceCard( roomId: entries[index], + showParents: false, + showVisibilityMark: true, margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), ), ), From 7e30d60ebe83f8c12ea06230140604782c0a2f0c Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 08:53:51 +0530 Subject: [PATCH 36/57] Manage local category list with provider --- .../categories/organized_categories.dart | 14 +- .../providers/categories_providers.dart | 23 ++++ .../categories/utils/category_utils.dart | 124 ++++++++++-------- app/lib/features/spaces/pages/sub_spaces.dart | 45 +++---- 4 files changed, 109 insertions(+), 97 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index 623d9d3066ab..ed16f60dac44 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -4,15 +4,13 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; -import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/add_edit_category.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; -import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; class OrganizedCategories extends ConsumerStatefulWidget { final String spaceId; @@ -40,17 +38,11 @@ class _DraggableCategoriesListState extends ConsumerState { } void setDragAndDropList() async { - final categoriesManager = await ref.read( - categoryManagerProvider( + categoryList = await ref.read( + localCategoryListProvider( (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), ).future, ); - final subSpaceList = - await ref.read(subSpacesListProvider(widget.spaceId).future); - categoryList = getCategorisedSubSpaces( - categoriesManager.categories().toList(), - subSpaceList, - ); setDragAndDropListData(); } diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart index 86a1413ab578..4ee6feb72475 100644 --- a/app/lib/features/categories/providers/categories_providers.dart +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -1,4 +1,7 @@ import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; +import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -16,3 +19,23 @@ final categoryManagerProvider = } throw 'Space not found'; }); + +final localCategoryListProvider = + FutureProvider.family, CategoriesInfo>( + (ref, categoryInfo) async { + final categoriesManager = await ref.read( + categoryManagerProvider( + ( + spaceId: categoryInfo.spaceId, + categoriesFor: categoryInfo.categoriesFor + ), + ).future, + ); + final subSpaceList = + await ref.read(subSpacesListProvider(categoryInfo.spaceId).future); + final categoryList = CategoryUtils().getCategorisedSubSpaces( + categoriesManager.categories().toList(), + subSpaceList, + ); + return categoryList; +}); diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 023625638511..ee7ff7611b30 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -10,79 +10,89 @@ CategoriesFor getCategoryEnumFromName(String name) { return CategoriesFor.values.firstWhere((v) => v.name == name); } -List getCategorisedSubSpacesWithoutEmptyList( - List categoryList, - List subSpaceList, -) { +class CategoryUtils { + static final CategoryUtils _singleton = CategoryUtils._internal(); + + factory CategoryUtils() { + return _singleton; + } + + CategoryUtils._internal(); + + List getCategorisedSubSpacesWithoutEmptyList( + List categoryList, + List subSpaceList, + ) { //CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST - List categoryListLocal = - getCategorisedSubSpaces(categoryList, subSpaceList); + List categoryListLocal = + getCategorisedSubSpaces(categoryList, subSpaceList); - List categoryListLocalWithoutEmptyEntries = []; - for (var categoryListLocal in categoryListLocal) { - if (categoryListLocal.entries.isNotEmpty) { - categoryListLocalWithoutEmptyEntries.add(categoryListLocal); + List categoryListLocalWithoutEmptyEntries = []; + for (var categoryListLocal in categoryListLocal) { + if (categoryListLocal.entries.isNotEmpty) { + categoryListLocalWithoutEmptyEntries.add(categoryListLocal); + } } + return categoryListLocalWithoutEmptyEntries; } - return categoryListLocalWithoutEmptyEntries; -} -List getCategorisedSubSpaces( - List categoryList, - List subSpaceList, -) { + List getCategorisedSubSpaces( + List categoryList, + List subSpaceList, + ) { //CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST - List categoryListLocal = - getLocalCategoryList(categoryList); + List categoryListLocal = + getLocalCategoryList(categoryList); //GET CATEGORIES SPACE IDs - List categoriesSpaceIds = []; - for (var spaceId in subSpaceList) { - for (var categoryItemLocal in categoryListLocal) { - if (categoryItemLocal.entries.contains(spaceId)) { - categoriesSpaceIds.add(spaceId); + List categoriesSpaceIds = []; + for (var spaceId in subSpaceList) { + for (var categoryItemLocal in categoryListLocal) { + if (categoryItemLocal.entries.contains(spaceId)) { + categoriesSpaceIds.add(spaceId); + } } } - } //GET UN-CATEGORIES SPACE IDs - List unCategoriesSpaceIds = subSpaceList; - for (var spaceId in categoriesSpaceIds) { - unCategoriesSpaceIds.remove(spaceId); - } + List unCategoriesSpaceIds = subSpaceList; + for (var spaceId in categoriesSpaceIds) { + unCategoriesSpaceIds.remove(spaceId); + } //ADD UN-CATEGORIES ITEM - CategoryModelLocal unCategorized = CategoryModelLocal( - entries: unCategoriesSpaceIds, - title: 'Un-categorized', - icon: ActerIcon.list, - color: Colors.blueGrey, - ); - categoryListLocal.add(unCategorized); - - return categoryListLocal; -} - -List getLocalCategoryList(List categoryList) { - List categoryListLocal = []; - for (var categoryItem in categoryList) { - final title = categoryItem.title(); - final color = convertColor( - categoryItem.display()?.color(), - iconPickerColors[0], + CategoryModelLocal unCategorized = CategoryModelLocal( + entries: unCategoriesSpaceIds, + title: 'Un-categorized', + icon: ActerIcon.list, + color: Colors.blueGrey, ); - final icon = ActerIcon.iconForPin(categoryItem.display()?.iconStr()); - final entries = - categoryItem.entries().map((s) => s.toDartString()).toList(); + categoryListLocal.add(unCategorized); - CategoryModelLocal categoryModelLocal = CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: entries, - ); - categoryListLocal.add(categoryModelLocal); + return categoryListLocal; } - return categoryListLocal; + List getLocalCategoryList(List categoryList) { + List categoryListLocal = []; + for (var categoryItem in categoryList) { + final title = categoryItem.title(); + final color = convertColor( + categoryItem.display()?.color(), + iconPickerColors[0], + ); + final icon = ActerIcon.iconForPin(categoryItem.display()?.iconStr()); + final entries = + categoryItem.entries().map((s) => s.toDartString()).toList(); + + CategoryModelLocal categoryModelLocal = CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: entries, + ); + categoryListLocal.add(categoryModelLocal); + } + + return categoryListLocal; + } } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index e6668841eb81..e50ca452326e 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -3,7 +3,6 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; -import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:atlas_icons/atlas_icons.dart'; @@ -128,36 +127,24 @@ class SubSpaces extends ConsumerWidget { } Widget _buildSubSpacesUI(BuildContext context, WidgetRef ref) { - final subSpaceList = ref.watch(subSpacesListProvider(spaceId)); + final localCategoryList = ref.watch( + localCategoryListProvider( + ( + spaceId: spaceId, + categoriesFor: CategoriesFor.spaces, + ), + ), + ); - return subSpaceList.when( - data: (subSpaceListData) { - final categoryManager = ref.watch( - categoryManagerProvider( - (spaceId: spaceId, categoriesFor: CategoriesFor.spaces), - ), - ); - return categoryManager.when( - data: (categoryManagerData) { - final List categoryList = - getCategorisedSubSpacesWithoutEmptyList( - categoryManagerData.categories().toList(), - subSpaceListData, - ); - return ListView.builder( - scrollDirection: Axis.vertical, - shrinkWrap: true, - itemCount: categoryList.length, - itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(context, categoryList[index]); - }, - ); - }, - error: (e, s) { - _log.severe('Failed to load the space categories', e, s); - return Center(child: Text(L10n.of(context).loadingFailed(e))); + return localCategoryList.when( + data: (localCategoryListData) { + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: localCategoryListData.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(context, localCategoryListData[index]); }, - loading: () => Center(child: Text(L10n.of(context).loading)), ); }, error: (e, s) { From a89e61e7b7cf9193e0f2dd36a63471848a17622b Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 10:15:33 +0530 Subject: [PATCH 37/57] General code improvement --- .../categories/organized_categories.dart | 112 ++++++++++-------- 1 file changed, 60 insertions(+), 52 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index ed16f60dac44..a0f79d8beb03 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -38,72 +38,80 @@ class _DraggableCategoriesListState extends ConsumerState { } void setDragAndDropList() async { + //GET LOCAL CATEGORY LIST categoryList = await ref.read( localCategoryListProvider( (spaceId: widget.spaceId, categoriesFor: widget.categoriesFor), ).future, ); + + //SET DRAG AND DROP LIST DATA BASED ON THE LOCAL CATEGORY LIST setDragAndDropListData(); } void setDragAndDropListData() { - dragAndDropList = List.generate(categoryList.length, (indexCategory) { + dragAndDropList = List.generate(categoryList.length, (categoryIndex) { return DragAndDropList( - canDrag: categoryList[indexCategory].title != 'Un-categorized', - header: Padding( - padding: const EdgeInsets.only(top: 18, bottom: 8), - child: CategoryHeaderView( - categoryModelLocal: categoryList[indexCategory], - isShowDragHandle: true, - headerBackgroundColor: - Theme.of(context).unselectedWidgetColor.withOpacity(0.7), - onClickEditCategory: () async { - showAddEditCategoryBottomSheet( - context: context, - title: categoryList[indexCategory].title, - color: categoryList[indexCategory].color, - icon: categoryList[indexCategory].icon, - onSave: (title, color, icon) { - CategoryModelLocal categoryModelLocal = CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: categoryList[indexCategory].entries, - ); - categoryList[indexCategory] = categoryModelLocal; - setDragAndDropListData(); - }, - ); - }, - onClickDeleteCategory: () async { - categoryList.removeAt(indexCategory); - await saveCategories( - context, - ref, - widget.spaceId, - CategoriesFor.spaces, - categoryList, - ); - setDragAndDropListData(); - }, - ), - ), - children: List.generate( - categoryList[indexCategory].entries.length, - (indexEntry) => DragAndDropItem( - child: SpaceCard( - roomId: - categoryList[indexCategory].entries[indexEntry].toString(), - margin: const EdgeInsets.symmetric(vertical: 6), - leading: Icon(PhosphorIcons.dotsSixVertical()), - ), - ), - ), + canDrag: categoryList[categoryIndex].title != 'Un-categorized', + header: dragDropListHeaderView(categoryIndex), + children: getDragAndDropItemList(categoryIndex), ); }); setState(() {}); } + Widget dragDropListHeaderView(int categoryIndex) { + return Padding( + padding: const EdgeInsets.only(top: 18, bottom: 8), + child: CategoryHeaderView( + categoryModelLocal: categoryList[categoryIndex], + isShowDragHandle: true, + headerBackgroundColor: + Theme.of(context).unselectedWidgetColor.withOpacity(0.7), + onClickEditCategory: () => callEditCategory(categoryIndex), + onClickDeleteCategory: () => callDeleteCategory(categoryIndex), + ), + ); + } + + void callEditCategory(int categoryIndex) { + showAddEditCategoryBottomSheet( + context: context, + title: categoryList[categoryIndex].title, + color: categoryList[categoryIndex].color, + icon: categoryList[categoryIndex].icon, + onSave: (title, color, icon) { + CategoryModelLocal categoryModelLocal = CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: categoryList[categoryIndex].entries, + ); + categoryList[categoryIndex] = categoryModelLocal; + setDragAndDropListData(); + }, + ); + } + + void callDeleteCategory(int categoryIndex) async { + categoryList.removeAt(categoryIndex); + setDragAndDropListData(); + } + + List getDragAndDropItemList(int categoryIndex) { + return List.generate( + categoryList[categoryIndex].entries.length, + (entryItemIndex) => DragAndDropItem( + child: SpaceCard( + roomId: + categoryList[categoryIndex].entries[entryItemIndex].toString(), + margin: const EdgeInsets.symmetric(vertical: 6), + leading: Icon(PhosphorIcons.dotsSixVertical()), + ), + ), + ); + } + @override Widget build(BuildContext context) { return Scaffold( @@ -177,7 +185,7 @@ class _DraggableCategoriesListState extends ConsumerState { widget.categoriesFor, categoryList, ); - if (context.mounted) Navigator.pop(context); + if (mounted) Navigator.pop(context); }, child: Text(L10n.of(context).save), ), From 7d40b78abcb1ef892469770463415b1b819a8b53 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 10:26:54 +0530 Subject: [PATCH 38/57] General code improvement --- .../categories/organized_categories.dart | 116 ++++++++++-------- 1 file changed, 64 insertions(+), 52 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index a0f79d8beb03..0df5cf409ffb 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -50,16 +50,18 @@ class _DraggableCategoriesListState extends ConsumerState { } void setDragAndDropListData() { - dragAndDropList = List.generate(categoryList.length, (categoryIndex) { - return DragAndDropList( - canDrag: categoryList[categoryIndex].title != 'Un-categorized', - header: dragDropListHeaderView(categoryIndex), - children: getDragAndDropItemList(categoryIndex), - ); + setState(() { + dragAndDropList = List.generate(categoryList.length, (categoryIndex) { + return DragAndDropList( + canDrag: categoryList[categoryIndex].title != 'Un-categorized', + header: dragDropListHeaderView(categoryIndex), + children: getDragAndDropItemList(categoryIndex), + ); + }); }); - setState(() {}); } + //HEADER ITEM VIEW Widget dragDropListHeaderView(int categoryIndex) { return Padding( padding: const EdgeInsets.only(top: 18, bottom: 8), @@ -74,6 +76,7 @@ class _DraggableCategoriesListState extends ConsumerState { ); } + //EDIT CATEGORY (LOCALLY) void callEditCategory(int categoryIndex) { showAddEditCategoryBottomSheet( context: context, @@ -93,11 +96,13 @@ class _DraggableCategoriesListState extends ConsumerState { ); } + //DELETE CATEGORY (LOCALLY) void callDeleteCategory(int categoryIndex) async { categoryList.removeAt(categoryIndex); setDragAndDropListData(); } + //DRAG AND DROP ITEM LIST VIEW List getDragAndDropItemList(int categoryIndex) { return List.generate( categoryList[categoryIndex].entries.length, @@ -129,6 +134,7 @@ class _DraggableCategoriesListState extends ConsumerState { ); } + //APPBAR VIEW AppBar _buildAppBarUI() { final spaceName = ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; @@ -153,55 +159,55 @@ class _DraggableCategoriesListState extends ConsumerState { onPressed: () => showAddEditCategoryBottomSheet( context: context, bottomSheetTitle: L10n.of(context).addCategory, - onSave: (title, color, icon) { - setState(() { - categoryList.insert( - categoryList.length - 1, - CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: [], - ), - ); - }); - setDragAndDropListData(); - }, + onSave: (title, color, icon) => callAddCategory(title, color, icon), ), ), ], ); } - Widget _buildSaveCategoriesButton() { - return Padding( - padding: const EdgeInsets.all(8.0), - child: ActerPrimaryActionButton( - onPressed: () async { - await saveCategories( - context, - ref, - widget.spaceId, - widget.categoriesFor, - categoryList, - ); - if (mounted) Navigator.pop(context); - }, - child: Text(L10n.of(context).save), - ), - ); + //ADD CATEGORY (LOCALLY) + void callAddCategory(title, color, icon) { + setState(() { + categoryList.insert( + 0, + CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: [], + ), + ); + }); } + //DRAG AND DROP LIST VIEW Widget _buildSubSpacesUIWithDrag() { return dragAndDropList == null - ? const SizedBox.shrink() + ? const Center(child: CircularProgressIndicator()) : DragAndDropLists( children: dragAndDropList!, - onItemReorder: _onItemReorder, onListReorder: _onListReorder, + onItemReorder: _onItemReorder, ); } + //ON HEADER ITEM REORDER + Future _onListReorder( + int oldListIndex, + int newListIndex, + ) async { + if (dragAndDropList == null) return; + setState(() { + var movedList = dragAndDropList!.removeAt(oldListIndex); + dragAndDropList!.insert(newListIndex, movedList); + + var movedCategoryList = categoryList.removeAt(oldListIndex); + categoryList.insert(newListIndex, movedCategoryList); + }); + } + + //ON SUB ITEM REORDER Future _onItemReorder( int oldItemIndex, int oldListIndex, @@ -220,17 +226,23 @@ class _DraggableCategoriesListState extends ConsumerState { }); } - Future _onListReorder( - int oldListIndex, - int newListIndex, - ) async { - if (dragAndDropList == null) return; - setState(() { - var movedList = dragAndDropList!.removeAt(oldListIndex); - dragAndDropList!.insert(newListIndex, movedList); - - var movedCategoryList = categoryList.removeAt(oldListIndex); - categoryList.insert(newListIndex, movedCategoryList); - }); + //SAVE ORGANIZED CATEGORIES + Widget _buildSaveCategoriesButton() { + return Padding( + padding: const EdgeInsets.all(8.0), + child: ActerPrimaryActionButton( + onPressed: () async { + await saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ); + if (mounted) Navigator.pop(context); + }, + child: Text(L10n.of(context).save), + ), + ); } } From 802f2fe8fef88fa4a78f0e98b6eb7540a79d6402 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 10:46:24 +0530 Subject: [PATCH 39/57] General code improvement --- .../categories/organized_categories.dart | 21 ++++---- .../providers/categories_providers.dart | 10 ++-- .../categories/utils/category_utils.dart | 48 ++++++++++--------- app/lib/features/spaces/pages/sub_spaces.dart | 7 ++- 4 files changed, 45 insertions(+), 41 deletions(-) diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organized_categories.dart index 0df5cf409ffb..3bd15d24ef63 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organized_categories.dart @@ -168,17 +168,16 @@ class _DraggableCategoriesListState extends ConsumerState { //ADD CATEGORY (LOCALLY) void callAddCategory(title, color, icon) { - setState(() { - categoryList.insert( - 0, - CategoryModelLocal( - title: title, - color: color, - icon: icon, - entries: [], - ), - ); - }); + categoryList.insert( + 0, + CategoryModelLocal( + title: title, + color: color, + icon: icon, + entries: [], + ), + ); + setDragAndDropListData(); } //DRAG AND DROP LIST VIEW diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart index 4ee6feb72475..62b62f05a1ac 100644 --- a/app/lib/features/categories/providers/categories_providers.dart +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -20,8 +20,8 @@ final categoryManagerProvider = throw 'Space not found'; }); -final localCategoryListProvider = - FutureProvider.family, CategoriesInfo>( +final localCategoryListProvider = FutureProvider.family + .autoDispose, CategoriesInfo>( (ref, categoryInfo) async { final categoriesManager = await ref.read( categoryManagerProvider( @@ -31,11 +31,11 @@ final localCategoryListProvider = ), ).future, ); - final subSpaceList = + final subSpacesList = await ref.read(subSpacesListProvider(categoryInfo.spaceId).future); - final categoryList = CategoryUtils().getCategorisedSubSpaces( + final categoryList = CategoryUtils().getCategorisedList( categoriesManager.categories().toList(), - subSpaceList, + subSpacesList, ); return categoryList; }); diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index ee7ff7611b30..5299ffc3acd1 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -11,6 +11,7 @@ CategoriesFor getCategoryEnumFromName(String name) { } class CategoryUtils { + ///CREATE SINGLETON CLASS OBJECT static final CategoryUtils _singleton = CategoryUtils._internal(); factory CategoryUtils() { @@ -19,16 +20,12 @@ class CategoryUtils { CategoryUtils._internal(); + ///GET LIST OF LOCAL CATEGORY WHICH EXCLUDE ITEM WITH EMPTY ENTRIES List getCategorisedSubSpacesWithoutEmptyList( - List categoryList, - List subSpaceList, + List categoryList, ) { -//CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST - List categoryListLocal = - getCategorisedSubSpaces(categoryList, subSpaceList); - List categoryListLocalWithoutEmptyEntries = []; - for (var categoryListLocal in categoryListLocal) { + for (var categoryListLocal in categoryList) { if (categoryListLocal.entries.isNotEmpty) { categoryListLocalWithoutEmptyEntries.add(categoryListLocal); } @@ -36,43 +33,48 @@ class CategoryUtils { return categoryListLocalWithoutEmptyEntries; } - List getCategorisedSubSpaces( + ///GET CATEGORIES LOCAL LIST BASED ON ITEM ENTRIES + List getCategorisedList( List categoryList, - List subSpaceList, + List entries, ) { -//CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST + //CONVERT CATEGORY LIST TO LOCAL CATEGORY LIST List categoryListLocal = - getLocalCategoryList(categoryList); + convertToLocalCategoryList(categoryList); -//GET CATEGORIES SPACE IDs - List categoriesSpaceIds = []; - for (var spaceId in subSpaceList) { + //GET CATEGORIES ENTRIES + List categoriesEntriesList = []; + for (var entryItem in entries) { for (var categoryItemLocal in categoryListLocal) { - if (categoryItemLocal.entries.contains(spaceId)) { - categoriesSpaceIds.add(spaceId); + if (categoryItemLocal.entries.contains(entryItem)) { + categoriesEntriesList.add(entryItem); } } } -//GET UN-CATEGORIES SPACE IDs - List unCategoriesSpaceIds = subSpaceList; - for (var spaceId in categoriesSpaceIds) { - unCategoriesSpaceIds.remove(spaceId); + //GET UN-CATEGORIES ENTRIES + List unCategoriesEntriesList = entries; + for (var entryItem in categoriesEntriesList) { + unCategoriesEntriesList.remove(entryItem); } -//ADD UN-CATEGORIES ITEM + //ADD UN-CATEGORIES ITEM to LAST POSITION CategoryModelLocal unCategorized = CategoryModelLocal( - entries: unCategoriesSpaceIds, + entries: unCategoriesEntriesList, title: 'Un-categorized', icon: ActerIcon.list, color: Colors.blueGrey, ); categoryListLocal.add(unCategorized); + //RETURN FINAL LOCAL CATEGORY LIST return categoryListLocal; } - List getLocalCategoryList(List categoryList) { + ///GET CATEGORY LIST TO LOCAL CATEGORY LIST + List convertToLocalCategoryList( + List categoryList, + ) { List categoryListLocal = []; for (var categoryItem in categoryList) { final title = categoryItem.title(); diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index e50ca452326e..78d8f37cf226 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -3,6 +3,7 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:atlas_icons/atlas_icons.dart'; @@ -138,12 +139,14 @@ class SubSpaces extends ConsumerWidget { return localCategoryList.when( data: (localCategoryListData) { + final categoryList = CategoryUtils() + .getCategorisedSubSpacesWithoutEmptyList(localCategoryListData); return ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, - itemCount: localCategoryListData.length, + itemCount: categoryList.length, itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(context, localCategoryListData[index]); + return _buildCategoriesList(context, categoryList[index]); }, ); }, From 8fd27849ea7becd7d569b20b70f71c4382359679 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 11:04:50 +0530 Subject: [PATCH 40/57] General code improvement --- app/lib/common/utils/routes.dart | 2 +- .../categories/actions/add_category.dart | 64 ------------------- ...tegories.dart => organize_categories.dart} | 8 +-- .../categories/utils/category_utils.dart | 9 +-- app/lib/features/spaces/pages/sub_spaces.dart | 2 +- .../shell_routers/home_shell_router.dart | 12 ++-- 6 files changed, 17 insertions(+), 80 deletions(-) delete mode 100644 app/lib/features/categories/actions/add_category.dart rename app/lib/features/categories/{organized_categories.dart => organize_categories.dart} (97%) diff --git a/app/lib/common/utils/routes.dart b/app/lib/common/utils/routes.dart index b3a7a4d026d9..af8e82b027c8 100644 --- a/app/lib/common/utils/routes.dart +++ b/app/lib/common/utils/routes.dart @@ -67,7 +67,7 @@ enum Routes { space('/:spaceId([!#][^/]+)'), // !spaceId, #spaceName spaceRelatedSpaces('/:spaceId([!#][^/]+)/spaces'), subSpaces('/:spaceId([!#][^/]+)/subSpaces'), - organizedCategories('/organizedCategories/:spaceId([^/]+)/:categoriesFor([^/]+)'), + organizeCategories('/organizeCategories/:spaceId([^/]+)/:categoriesFor([^/]+)'), spaceMembers('/:spaceId([!#][^/]+)/members'), spacePins('/:spaceId([!#][^/]+)/pins'), spaceEvents('/:spaceId([!#][^/]+)/events'), diff --git a/app/lib/features/categories/actions/add_category.dart b/app/lib/features/categories/actions/add_category.dart deleted file mode 100644 index 2ca63139f362..000000000000 --- a/app/lib/features/categories/actions/add_category.dart +++ /dev/null @@ -1,64 +0,0 @@ -import 'package:acter/common/providers/sdk_provider.dart'; -import 'package:acter/common/providers/space_providers.dart'; -import 'package:acter/common/widgets/acter_icon_picker/model/acter_icons.dart'; -import 'package:acter/features/categories/providers/categories_providers.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_easyloading/flutter_easyloading.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:logging/logging.dart'; - -final _log = Logger('a3::save_categories'); - -void addCategory( - BuildContext context, - WidgetRef ref, - String spaceId, - CategoriesFor categoriesFor, - String categoryTitle, - Color color, - ActerIcon icon, -) async { - // Show loading message - EasyLoading.show(status: L10n.of(context).addingNewCategory); - try { - //GET REQUIRE DATA FROM PROVIDERS - final categoriesManager = await ref.read( - categoryManagerProvider( - (spaceId: spaceId, categoriesFor: categoriesFor), - ).future, - ); - final sdk = await ref.watch(sdkProvider.future); - final displayBuilder = sdk.api.newDisplayBuilder(); - - //BUILD NEW CATEGORY - final newCategory = categoriesManager.newCategoryBuilder(); - newCategory.title(categoryTitle); - displayBuilder.color(color.value); - displayBuilder.icon('acter-icon', icon.name); - newCategory.display(displayBuilder.build()); - - //SAVE NEW CATEGORY in CATEGORIES BUILDER - final categoriesUpdateBuilder = categoriesManager.updateBuilder(); - categoriesUpdateBuilder.add(newCategory.build()); - - //SAVE UPDATED CATEGORIES BUILDER IN SPACE - final space = await ref.read(spaceProvider(spaceId).future); - space.setCategories(categoriesFor.name, categoriesUpdateBuilder); - - EasyLoading.dismiss(); - if (context.mounted) { - Navigator.pop(context); - } - } catch (e, s) { - _log.severe('Failed to add category', e, s); - if (!context.mounted) { - EasyLoading.dismiss(); - return; - } - EasyLoading.showError( - L10n.of(context).addingNewCategoriesFailed(e), - duration: const Duration(seconds: 3), - ); - } -} diff --git a/app/lib/features/categories/organized_categories.dart b/app/lib/features/categories/organize_categories.dart similarity index 97% rename from app/lib/features/categories/organized_categories.dart rename to app/lib/features/categories/organize_categories.dart index 3bd15d24ef63..28c677f16e39 100644 --- a/app/lib/features/categories/organized_categories.dart +++ b/app/lib/features/categories/organize_categories.dart @@ -12,22 +12,22 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; -class OrganizedCategories extends ConsumerStatefulWidget { +class OrganizeCategories extends ConsumerStatefulWidget { final String spaceId; final CategoriesFor categoriesFor; - const OrganizedCategories({ + const OrganizeCategories({ super.key, required this.spaceId, required this.categoriesFor, }); @override - ConsumerState createState() => + ConsumerState createState() => _DraggableCategoriesListState(); } -class _DraggableCategoriesListState extends ConsumerState { +class _DraggableCategoriesListState extends ConsumerState { List? dragAndDropList; late List categoryList; diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 5299ffc3acd1..d95c75b82acc 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -6,10 +6,6 @@ import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter/material.dart'; -CategoriesFor getCategoryEnumFromName(String name) { - return CategoriesFor.values.firstWhere((v) => v.name == name); -} - class CategoryUtils { ///CREATE SINGLETON CLASS OBJECT static final CategoryUtils _singleton = CategoryUtils._internal(); @@ -20,6 +16,11 @@ class CategoryUtils { CategoryUtils._internal(); + ///CATEGORY ENUM ITEM FROM NAME + CategoriesFor getCategoryEnumFromName(String name) { + return CategoriesFor.values.firstWhere((v) => v.name == name); + } + ///GET LIST OF LOCAL CATEGORY WHICH EXCLUDE ITEM WITH EMPTY ENTRIES List getCategorisedSubSpacesWithoutEmptyList( List categoryList, diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 78d8f37cf226..b8e6d72adbdf 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -109,7 +109,7 @@ class SubSpaces extends ConsumerWidget { ), PopupMenuItem( onTap: () => context.pushNamed( - Routes.organizedCategories.name, + Routes.organizeCategories.name, pathParameters: { 'spaceId': spaceId, 'categoriesFor': CategoriesFor.spaces.name, diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 79f5256b91d3..0ad68140325a 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -1,6 +1,6 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/with_sidebar.dart'; -import 'package:acter/features/categories/organized_categories.dart'; +import 'package:acter/features/categories/organize_categories.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/events/pages/create_event_page.dart'; import 'package:acter/features/events/pages/event_list_page.dart'; @@ -241,16 +241,16 @@ final homeShellRoutes = [ }, ), GoRoute( - name: Routes.organizedCategories.name, - path: Routes.organizedCategories.route, + name: Routes.organizeCategories.name, + path: Routes.organizeCategories.route, redirect: authGuardRedirect, pageBuilder: (context, state) { return NoTransitionPage( key: state.pageKey, - child: OrganizedCategories( + child: OrganizeCategories( spaceId: state.pathParameters['spaceId']!, - categoriesFor: - getCategoryEnumFromName(state.pathParameters['categoriesFor']!), + categoriesFor: CategoryUtils() + .getCategoryEnumFromName(state.pathParameters['categoriesFor']!), ), ); }, From d9f5c269f949e972bf4894480d7209b89057100b Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 11:22:54 +0530 Subject: [PATCH 41/57] Save organize categories on back and manage delete categories entries --- .../categories/organize_categories.dart | 18 ++++++++++++++++++ .../providers/categories_providers.dart | 5 ++--- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/organize_categories.dart b/app/lib/features/categories/organize_categories.dart index 28c677f16e39..48cab22da6ae 100644 --- a/app/lib/features/categories/organize_categories.dart +++ b/app/lib/features/categories/organize_categories.dart @@ -98,7 +98,12 @@ class _DraggableCategoriesListState extends ConsumerState { //DELETE CATEGORY (LOCALLY) void callDeleteCategory(int categoryIndex) async { + List entriesOfDeleteCategory = categoryList[categoryIndex].entries; + CategoryModelLocal unCategoriesItem = categoryList[categoryList.length - 1]; + unCategoriesItem.entries.addAll(entriesOfDeleteCategory); categoryList.removeAt(categoryIndex); + categoryList.removeAt(categoryList.length - 1); + categoryList.add(unCategoriesItem); setDragAndDropListData(); } @@ -139,6 +144,19 @@ class _DraggableCategoriesListState extends ConsumerState { final spaceName = ref.watch(roomDisplayNameProvider(widget.spaceId)).valueOrNull; return AppBar( + leading: IconButton( + onPressed: () async { + await saveCategories( + context, + ref, + widget.spaceId, + widget.categoriesFor, + categoryList, + ); + if (mounted) Navigator.pop(context); + }, + icon: const Icon(Icons.arrow_back), + ), title: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart index 62b62f05a1ac..45956d12ce22 100644 --- a/app/lib/features/categories/providers/categories_providers.dart +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -9,9 +9,8 @@ enum CategoriesFor { spaces, chats, pins } typedef CategoriesInfo = ({String spaceId, CategoriesFor categoriesFor}); -final categoryManagerProvider = - FutureProvider.family( - (ref, categoryInfo) async { +final categoryManagerProvider = FutureProvider.family + .autoDispose((ref, categoryInfo) async { final maybeSpace = await ref.watch(maybeSpaceProvider(categoryInfo.spaceId).future); if (maybeSpace != null) { From b746951450ecef36339a19dccfddba9bb63a5e77 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 11:26:17 +0530 Subject: [PATCH 42/57] Minor fixes --- .../categories/organize_categories.dart | 28 +++++++++---------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/app/lib/features/categories/organize_categories.dart b/app/lib/features/categories/organize_categories.dart index 48cab22da6ae..53caf38ece57 100644 --- a/app/lib/features/categories/organize_categories.dart +++ b/app/lib/features/categories/organize_categories.dart @@ -215,13 +215,13 @@ class _DraggableCategoriesListState extends ConsumerState { int newListIndex, ) async { if (dragAndDropList == null) return; - setState(() { - var movedList = dragAndDropList!.removeAt(oldListIndex); - dragAndDropList!.insert(newListIndex, movedList); + var movedList = dragAndDropList!.removeAt(oldListIndex); + dragAndDropList!.insert(newListIndex, movedList); - var movedCategoryList = categoryList.removeAt(oldListIndex); - categoryList.insert(newListIndex, movedCategoryList); - }); + var movedCategoryList = categoryList.removeAt(oldListIndex); + categoryList.insert(newListIndex, movedCategoryList); + + setDragAndDropListData(); } //ON SUB ITEM REORDER @@ -232,15 +232,15 @@ class _DraggableCategoriesListState extends ConsumerState { int newListIndex, ) async { if (dragAndDropList == null) return; - setState(() { - var movedItem = - dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); - dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); + var movedItem = + dragAndDropList![oldListIndex].children.removeAt(oldItemIndex); + dragAndDropList![newListIndex].children.insert(newItemIndex, movedItem); - var movedEntryItem = - categoryList[oldListIndex].entries.removeAt(oldItemIndex); - categoryList[newListIndex].entries.insert(newItemIndex, movedEntryItem); - }); + var movedEntryItem = + categoryList[oldListIndex].entries.removeAt(oldItemIndex); + categoryList[newListIndex].entries.insert(newItemIndex, movedEntryItem); + + setDragAndDropListData(); } //SAVE ORGANIZED CATEGORIES From aa49437712ca120e0f5472942bb34a8e13f487ec Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 11:27:47 +0530 Subject: [PATCH 43/57] Wording correction --- app/lib/features/categories/organize_categories.dart | 2 +- app/lib/features/spaces/pages/sub_spaces.dart | 2 +- app/lib/l10n/app_en.arb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/organize_categories.dart b/app/lib/features/categories/organize_categories.dart index 53caf38ece57..e3a7078a6492 100644 --- a/app/lib/features/categories/organize_categories.dart +++ b/app/lib/features/categories/organize_categories.dart @@ -161,7 +161,7 @@ class _DraggableCategoriesListState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - L10n.of(context).organized, + L10n.of(context).organize, style: Theme.of(context).textTheme.titleLarge, ), Text( diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index b8e6d72adbdf..e4768870f9ce 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -119,7 +119,7 @@ class SubSpaces extends ConsumerWidget { children: [ Icon(PhosphorIcons.dotsSixVertical()), const SizedBox(width: 6), - Text(L10n.of(context).organized), + Text(L10n.of(context).organize), ], ), ), diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index dfc73c77c9df..24a2175837e1 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2188,7 +2188,7 @@ "selectColor": "Select color", "selectIcon": "Select icon", "createCategory": "Create Category", - "organized": "Organized", + "organize": "Organize", "updatingCategories": "Updating categories", "updatingCategoriesFailed": "Updating categories failed {error}", "addingNewCategory": "Adding new category", From d9d595277ead3deaf3cdaf99e4fcda18f580030b Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 11:55:38 +0530 Subject: [PATCH 44/57] Dummy category validation code improvement --- app/lib/features/categories/actions/save_categories.dart | 8 +++++--- .../features/categories/model/CategoryModelLocal.dart | 9 ++++----- app/lib/features/categories/organize_categories.dart | 4 +++- app/lib/features/categories/utils/category_utils.dart | 8 +++++--- .../categories/widgets/category_header_view.dart | 7 ++++--- 5 files changed, 21 insertions(+), 15 deletions(-) diff --git a/app/lib/features/categories/actions/save_categories.dart b/app/lib/features/categories/actions/save_categories.dart index 252631684e3c..8c183d4bfa9c 100644 --- a/app/lib/features/categories/actions/save_categories.dart +++ b/app/lib/features/categories/actions/save_categories.dart @@ -2,6 +2,7 @@ import 'package:acter/common/providers/sdk_provider.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_easyloading/flutter_easyloading.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -35,14 +36,15 @@ Future saveCategories( //Clear category builder data and Add new categoriesBuilder.clear(); for (int i = 0; i < categoryList.length; i++) { - if (categoryList[i].title != 'Un-categorized') { + bool isValidCategory = CategoryUtils().isValidCategory(categoryList[i]); + if (isValidCategory) { final newCategoryItem = categoriesManager.newCategoryBuilder(); //ADD TITLE newCategoryItem.title(categoryList[i].title); //ADD COLOR AND ICON - displayBuilder.color(categoryList[i].color.value); - displayBuilder.icon('acter-icon', categoryList[i].icon.name); + displayBuilder.color(categoryList[i].color!.value); + displayBuilder.icon('acter-icon', categoryList[i].icon!.name); newCategoryItem.display(displayBuilder.build()); //ADD ENTRIES diff --git a/app/lib/features/categories/model/CategoryModelLocal.dart b/app/lib/features/categories/model/CategoryModelLocal.dart index 2c3f3803f34c..737cf8e1a048 100644 --- a/app/lib/features/categories/model/CategoryModelLocal.dart +++ b/app/lib/features/categories/model/CategoryModelLocal.dart @@ -3,15 +3,14 @@ import 'package:flutter/material.dart'; class CategoryModelLocal { final String title; - final Color color; - final ActerIcon icon; + final Color? color; + final ActerIcon? icon; final List entries; const CategoryModelLocal({ required this.title, - required this.color, - required this.icon, + this.color, + this.icon, required this.entries, }); } - diff --git a/app/lib/features/categories/organize_categories.dart b/app/lib/features/categories/organize_categories.dart index e3a7078a6492..b6042872931f 100644 --- a/app/lib/features/categories/organize_categories.dart +++ b/app/lib/features/categories/organize_categories.dart @@ -4,6 +4,7 @@ import 'package:acter/common/widgets/spaces/space_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/add_edit_category.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:drag_and_drop_lists/drag_and_drop_lists.dart'; @@ -53,7 +54,8 @@ class _DraggableCategoriesListState extends ConsumerState { setState(() { dragAndDropList = List.generate(categoryList.length, (categoryIndex) { return DragAndDropList( - canDrag: categoryList[categoryIndex].title != 'Un-categorized', + canDrag: + CategoryUtils().isValidCategory(categoryList[categoryIndex]), header: dragDropListHeaderView(categoryIndex), children: getDragAndDropItemList(categoryIndex), ); diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index d95c75b82acc..8999ae451b0e 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -4,7 +4,6 @@ import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; -import 'package:flutter/material.dart'; class CategoryUtils { ///CREATE SINGLETON CLASS OBJECT @@ -21,6 +20,11 @@ class CategoryUtils { return CategoriesFor.values.firstWhere((v) => v.name == name); } + ///CHECK FOR UN-CATEGORIZED TYPE + bool isValidCategory(CategoryModelLocal category) { + return category.color != null && category.icon != null; + } + ///GET LIST OF LOCAL CATEGORY WHICH EXCLUDE ITEM WITH EMPTY ENTRIES List getCategorisedSubSpacesWithoutEmptyList( List categoryList, @@ -63,8 +67,6 @@ class CategoryUtils { CategoryModelLocal unCategorized = CategoryModelLocal( entries: unCategoriesEntriesList, title: 'Un-categorized', - icon: ActerIcon.list, - color: Colors.blueGrey, ); categoryListLocal.add(unCategorized); diff --git a/app/lib/features/categories/widgets/category_header_view.dart b/app/lib/features/categories/widgets/category_header_view.dart index 56b9af0a9787..d67007b50395 100644 --- a/app/lib/features/categories/widgets/category_header_view.dart +++ b/app/lib/features/categories/widgets/category_header_view.dart @@ -1,5 +1,6 @@ import 'package:acter/common/widgets/acter_icon_picker/acter_icon_widget.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:flutter/material.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; @@ -22,9 +23,9 @@ class CategoryHeaderView extends StatelessWidget { @override Widget build(BuildContext context) { - return (categoryModelLocal.title == 'Un-categorized') - ? _buildUnCategoriesHeader(context) - : _buildCategoryHeader(context); + return CategoryUtils().isValidCategory(categoryModelLocal) + ? _buildCategoryHeader(context) + : _buildUnCategoriesHeader(context); } Widget _buildCategoryHeader(BuildContext context) { From 1b65cc3f282fdd7bec003c7c4db9731d7a918103 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 12:09:55 +0530 Subject: [PATCH 45/57] Wording improvement --- ...nize_categories.dart => organize_categories_page.dart} | 8 ++++---- app/lib/router/shell_routers/home_shell_router.dart | 4 ++-- 2 files changed, 6 insertions(+), 6 deletions(-) rename app/lib/features/categories/{organize_categories.dart => organize_categories_page.dart} (97%) diff --git a/app/lib/features/categories/organize_categories.dart b/app/lib/features/categories/organize_categories_page.dart similarity index 97% rename from app/lib/features/categories/organize_categories.dart rename to app/lib/features/categories/organize_categories_page.dart index b6042872931f..db39d95a083c 100644 --- a/app/lib/features/categories/organize_categories.dart +++ b/app/lib/features/categories/organize_categories_page.dart @@ -13,22 +13,22 @@ import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:phosphor_flutter/phosphor_flutter.dart'; -class OrganizeCategories extends ConsumerStatefulWidget { +class OrganizeCategoriesPage extends ConsumerStatefulWidget { final String spaceId; final CategoriesFor categoriesFor; - const OrganizeCategories({ + const OrganizeCategoriesPage({ super.key, required this.spaceId, required this.categoriesFor, }); @override - ConsumerState createState() => + ConsumerState createState() => _DraggableCategoriesListState(); } -class _DraggableCategoriesListState extends ConsumerState { +class _DraggableCategoriesListState extends ConsumerState { List? dragAndDropList; late List categoryList; diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index 0ad68140325a..042a698d0e40 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -1,6 +1,6 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/with_sidebar.dart'; -import 'package:acter/features/categories/organize_categories.dart'; +import 'package:acter/features/categories/organize_categories_page.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/events/pages/create_event_page.dart'; import 'package:acter/features/events/pages/event_list_page.dart'; @@ -247,7 +247,7 @@ final homeShellRoutes = [ pageBuilder: (context, state) { return NoTransitionPage( key: state.pageKey, - child: OrganizeCategories( + child: OrganizeCategoriesPage( spaceId: state.pathParameters['spaceId']!, categoriesFor: CategoryUtils() .getCategoryEnumFromName(state.pathParameters['categoriesFor']!), From 969e39d66362bd073736a916b55ebf476d78e1e1 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 12:41:24 +0530 Subject: [PATCH 46/57] Fixed last category item view cut issue --- app/lib/features/categories/organize_categories_page.dart | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/lib/features/categories/organize_categories_page.dart b/app/lib/features/categories/organize_categories_page.dart index db39d95a083c..7e0d5e50448f 100644 --- a/app/lib/features/categories/organize_categories_page.dart +++ b/app/lib/features/categories/organize_categories_page.dart @@ -28,7 +28,8 @@ class OrganizeCategoriesPage extends ConsumerStatefulWidget { _DraggableCategoriesListState(); } -class _DraggableCategoriesListState extends ConsumerState { +class _DraggableCategoriesListState + extends ConsumerState { List? dragAndDropList; late List categoryList; @@ -53,11 +54,12 @@ class _DraggableCategoriesListState extends ConsumerState Date: Wed, 18 Sep 2024 13:11:59 +0530 Subject: [PATCH 47/57] Changes related to merge with main --- app/lib/common/utils/routes.dart | 1 - .../categories/organize_categories_page.dart | 4 ++-- .../widgets/space_sections/spaces_section.dart | 2 +- app/lib/features/spaces/pages/sub_spaces.dart | 4 ++-- .../router/shell_routers/home_shell_router.dart | 14 -------------- 5 files changed, 5 insertions(+), 20 deletions(-) diff --git a/app/lib/common/utils/routes.dart b/app/lib/common/utils/routes.dart index af8e82b027c8..7b9414530f1a 100644 --- a/app/lib/common/utils/routes.dart +++ b/app/lib/common/utils/routes.dart @@ -65,7 +65,6 @@ enum Routes { linkRecommended('/:spaceId([!#][^/]+)/linkRecommended'), spaceInvite('/:spaceId([!#][^/]+)/invite'), space('/:spaceId([!#][^/]+)'), // !spaceId, #spaceName - spaceRelatedSpaces('/:spaceId([!#][^/]+)/spaces'), subSpaces('/:spaceId([!#][^/]+)/subSpaces'), organizeCategories('/organizeCategories/:spaceId([^/]+)/:categoriesFor([^/]+)'), spaceMembers('/:spaceId([!#][^/]+)/members'), diff --git a/app/lib/features/categories/organize_categories_page.dart b/app/lib/features/categories/organize_categories_page.dart index 7e0d5e50448f..990c0252d7ac 100644 --- a/app/lib/features/categories/organize_categories_page.dart +++ b/app/lib/features/categories/organize_categories_page.dart @@ -1,6 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; -import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/common/widgets/room/room_card.dart'; import 'package:acter/features/categories/actions/save_categories.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; @@ -116,7 +116,7 @@ class _DraggableCategoriesListState return List.generate( categoryList[categoryIndex].entries.length, (entryItemIndex) => DragAndDropItem( - child: SpaceCard( + child: RoomCard( roomId: categoryList[categoryIndex].entries[entryItemIndex].toString(), margin: const EdgeInsets.symmetric(vertical: 6), diff --git a/app/lib/features/space/widgets/space_sections/spaces_section.dart b/app/lib/features/space/widgets/space_sections/spaces_section.dart index eb888d5f909a..cd8999918256 100644 --- a/app/lib/features/space/widgets/space_sections/spaces_section.dart +++ b/app/lib/features/space/widgets/space_sections/spaces_section.dart @@ -71,7 +71,7 @@ class SpacesSection extends ConsumerWidget { title: L10n.of(context).suggestedSpaces, isShowSeeAllButton: true, onTapSeeAll: () => context.pushNamed( - Routes.spaceRelatedSpaces.name, + Routes.subSpaces.name, pathParameters: {'spaceId': spaceId}, ), ), diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index e4768870f9ce..19f814b7119e 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,6 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/utils/routes.dart'; -import 'package:acter/common/widgets/spaces/space_card.dart'; +import 'package:acter/common/widgets/room/room_card.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; @@ -172,7 +172,7 @@ class SubSpaces extends ConsumerWidget { title: CategoryHeaderView(categoryModelLocal: categoryModelLocal), children: List.generate( entries.length, - (index) => SpaceCard( + (index) => RoomCard( roomId: entries[index], showParents: false, showVisibilityMark: true, diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index f033eb38d6bb..af04c762486f 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -33,7 +33,6 @@ import 'package:acter/features/spaces/pages/sub_spaces.dart'; import 'package:acter/features/super_invites/pages/super_invites.dart'; import 'package:acter/features/space/pages/chats_page.dart'; import 'package:acter/features/space/pages/members_page.dart'; -import 'package:acter/features/space/pages/sub_spaces_page.dart'; import 'package:acter/features/space/settings/pages/apps_settings_page.dart'; import 'package:acter/features/space/settings/pages/index_page.dart'; import 'package:acter/features/space/settings/pages/notification_configuration_page.dart'; @@ -215,19 +214,6 @@ final homeShellRoutes = [ ); }, ), - GoRoute( - name: Routes.spaceRelatedSpaces.name, - path: Routes.spaceRelatedSpaces.route, - redirect: authGuardRedirect, - pageBuilder: (context, state) { - return NoTransitionPage( - key: state.pageKey, - child: SubSpacesPage( - spaceIdOrAlias: state.pathParameters['spaceId']!, - ), - ); - }, - ), GoRoute( name: Routes.subSpaces.name, path: Routes.subSpaces.route, From dbb070f9f37ae38b3821a526bb1cb4543bf18e95 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 13:19:46 +0530 Subject: [PATCH 48/57] Remove older sub-spaces page --- app/integration_test/tests/sub_spaces.dart | 10 +- .../features/space/pages/sub_spaces_page.dart | 193 ------------------ .../space/widgets/related/spaces_helpers.dart | 88 -------- 3 files changed, 5 insertions(+), 286 deletions(-) delete mode 100644 app/lib/features/space/pages/sub_spaces_page.dart diff --git a/app/integration_test/tests/sub_spaces.dart b/app/integration_test/tests/sub_spaces.dart index 8b2404211886..7b1587f548a1 100644 --- a/app/integration_test/tests/sub_spaces.dart +++ b/app/integration_test/tests/sub_spaces.dart @@ -1,6 +1,6 @@ import 'package:acter/common/widgets/sliver_scaffold.dart'; import 'package:acter/features/space/sheets/link_room_sheet.dart'; -import 'package:acter/features/space/pages/sub_spaces_page.dart'; +import 'package:acter/features/spaces/pages/sub_spaces.dart'; import 'package:convenient_test_dev/convenient_test_dev.dart'; import 'package:flutter/material.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -42,8 +42,8 @@ void subSpaceTests() { await t.gotoSpace(spaceId); await t.navigateTo([ const Key('spaces'), - SubSpacesPage.moreOptionKey, - SubSpacesPage.linkSubspaceKey, + SubSpaces.moreOptionKey, + SubSpaces.linkSubspaceKey, ]); final roomListEntry = find.byKey(Key('room-list-link-$subSpace')); @@ -89,8 +89,8 @@ void subSpaceTests() { await t.gotoSpace(spaceId); await t.navigateTo([ const Key('spaces'), - SubSpacesPage.moreOptionKey, - SubSpacesPage.linkSubspaceKey, + SubSpaces.moreOptionKey, + SubSpaces.linkSubspaceKey, ]); final roomListEntry = find.byKey(Key('room-list-link-$subSpace')); diff --git a/app/lib/features/space/pages/sub_spaces_page.dart b/app/lib/features/space/pages/sub_spaces_page.dart deleted file mode 100644 index fb2d13fff412..000000000000 --- a/app/lib/features/space/pages/sub_spaces_page.dart +++ /dev/null @@ -1,193 +0,0 @@ -import 'dart:math'; - -import 'package:acter/common/providers/room_providers.dart'; -import 'package:acter/common/providers/space_providers.dart'; -import 'package:acter/common/toolkit/buttons/inline_text_button.dart'; -import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; -import 'package:acter/common/utils/routes.dart'; -import 'package:acter/common/widgets/empty_state_widget.dart'; -import 'package:acter/features/space/widgets/related/spaces_helpers.dart'; -import 'package:atlas_icons/atlas_icons.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:logging/logging.dart'; - -final _log = Logger('a3::space::sub_spaces'); - -class SubSpacesPage extends ConsumerWidget { - static const moreOptionKey = Key('related-spaces-more-actions'); - static const createSubspaceKey = Key('related-spaces-more-create-subspace'); - static const linkSubspaceKey = Key('related-spaces-more-link-subspace'); - - final String spaceIdOrAlias; - - const SubSpacesPage({super.key, required this.spaceIdOrAlias}); - - Widget _renderTools(BuildContext context) { - return PopupMenuButton( - icon: const Icon(Atlas.plus_circle, key: moreOptionKey), - iconSize: 28, - color: Theme.of(context).colorScheme.surface, - itemBuilder: (BuildContext context) => [ - PopupMenuItem( - key: createSubspaceKey, - onTap: () => context.pushNamed( - Routes.createSpace.name, - queryParameters: {'parentSpaceId': spaceIdOrAlias}, - ), - child: Row( - children: [ - Text(L10n.of(context).createSubspace), - const Spacer(), - const Icon(Atlas.connection), - ], - ), - ), - PopupMenuItem( - key: linkSubspaceKey, - onTap: () => context.pushNamed( - Routes.linkSubspace.name, - pathParameters: {'spaceId': spaceIdOrAlias}, - ), - child: Row( - children: [ - Text(L10n.of(context).linkExistingSpace), - const Spacer(), - const Icon(Atlas.connection), - ], - ), - ), - PopupMenuItem( - onTap: () => context.pushNamed( - Routes.linkRecommended.name, - pathParameters: {'spaceId': spaceIdOrAlias}, - ), - child: Row( - children: [ - Text(L10n.of(context).recommendedSpaces), - const Spacer(), - const Icon(Atlas.plus_circle), - ], - ), - ), - ], - ); - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - final spacesLoader = - ref.watch(spaceRelationsOverviewProvider(spaceIdOrAlias)); - final widthCount = (MediaQuery.of(context).size.width ~/ 300).toInt(); - const int minCount = 3; - final crossAxisCount = max(1, min(widthCount, minCount)); - final spaceName = - ref.watch(roomDisplayNameProvider(spaceIdOrAlias)).valueOrNull; - final membership = ref.watch(roomMembershipProvider(spaceIdOrAlias)); - bool canLinkSpace = - membership.valueOrNull?.canString('CanLinkSpaces') == true; - // get platform of context. - return Scaffold( - appBar: AppBar( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(L10n.of(context).spaces), - Text( - '($spaceName)', - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelLarge, - ), - ], - ), - actions: [ - IconButton( - icon: const Icon(Atlas.arrows_rotating_right_thin), - iconSize: 28, - color: Theme.of(context).colorScheme.surface, - onPressed: () async { - ref.invalidate(spaceRelationsProvider); - }, - ), - spacesLoader.when( - data: (spaces) { - if (canLinkSpace) { - return _renderTools(context); - } else { - return const SizedBox.shrink(); - } - }, - error: (e, s) { - _log.severe('Failed to load the related spaces', e, s); - return Center( - child: Text(L10n.of(context).loadingFailed(e)), - ); - }, - loading: () => const SizedBox.shrink(), - ), - ], - ), - body: SingleChildScrollView( - child: Column( - children: [ - spacesLoader.when( - data: (spaces) { - final subspaces = renderSubSpaces( - context, - ref, - spaceIdOrAlias, - spaces, - crossAxisCount: crossAxisCount, - ); - if (subspaces != null) return subspaces; - return renderFallback(context, canLinkSpace); - }, - error: (e, s) { - _log.severe('Failed to load the related spaces', e, s); - return Center( - child: Text(L10n.of(context).loadingFailed(e)), - ); - }, - loading: () => Center( - child: Text(L10n.of(context).loading), - ), - ), - ], - ), - ), - ); - } - - Widget renderFallback(BuildContext context, bool canLinkSpace) { - return Center( - heightFactor: 1, - child: EmptyState( - title: L10n.of(context).noConnectedSpaces, - subtitle: L10n.of(context).inConnectedSpaces, - image: 'assets/images/empty_space.svg', - primaryButton: canLinkSpace - ? ActerPrimaryActionButton( - onPressed: () => context.pushNamed( - Routes.createSpace.name, - queryParameters: { - 'parentSpaceId': spaceIdOrAlias, - }, - ), - child: Text(L10n.of(context).createNewSpace), - ) - : null, - secondaryButton: canLinkSpace - ? ActerInlineTextButton( - onPressed: () => context.pushNamed( - Routes.linkSubspace.name, - pathParameters: {'spaceId': spaceIdOrAlias}, - ), - child: Text(L10n.of(context).linkExistingSpace), - ) - : null, - ), - ); - } -} diff --git a/app/lib/features/space/widgets/related/spaces_helpers.dart b/app/lib/features/space/widgets/related/spaces_helpers.dart index 0cb0cc520800..30c3db6342c3 100644 --- a/app/lib/features/space/widgets/related/spaces_helpers.dart +++ b/app/lib/features/space/widgets/related/spaces_helpers.dart @@ -2,7 +2,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/widgets/room/room_hierarchy_join_button.dart'; import 'package:acter/common/widgets/room/room_hierarchy_options_menu.dart'; -import 'package:acter/common/widgets/room/room_card.dart'; import 'package:acter/common/widgets/room/room_hierarchy_card.dart'; import 'package:acter/router/utils.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; @@ -14,46 +13,6 @@ import 'package:skeletonizer/skeletonizer.dart'; final _log = Logger('a3::space::related::spaces_helpers'); -List? _renderKnownSubspaces( - BuildContext context, - bool canLinkSpace, - String spaceIdOrAlias, - SpaceRelationsOverview spaces, -) { - if (spaces.knownSubspaces.isEmpty) { - return null; - } - - return [ - GridView.builder( - itemCount: spaces.knownSubspaces.length, - physics: const NeverScrollableScrollPhysics(), - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 1, - childAspectRatio: 4.0, - mainAxisExtent: 100, - ), - shrinkWrap: true, - itemBuilder: (context, index) { - final roomId = spaces.knownSubspaces[index]; - final isSuggested = spaces.suggestedIds.contains(roomId); - return RoomCard( - key: Key('subspace-list-item-$roomId'), - roomId: roomId, - showParents: false, - showSuggestedMark: isSuggested, - showVisibilityMark: true, - trailing: RoomHierarchyOptionsMenu( - childId: roomId, - parentId: spaceIdOrAlias, - isSuggested: isSuggested, - ), - ); - }, - ), - ]; -} - Widget renderRemoteSubspaces( BuildContext context, WidgetRef ref, @@ -148,50 +107,3 @@ Widget renderMoreSubspaces( ), ); } - -Widget? renderSubSpaces( - BuildContext context, - WidgetRef ref, - String spaceIdOrAlias, - SpaceRelationsOverview spaces, { - int crossAxisCount = 1, - Widget? Function()? titleBuilder, -}) { - final canLinkSpace = ref - .watch(roomMembershipProvider(spaceIdOrAlias)) - .valueOrNull - ?.canString('CanLinkSpaces') ?? - false; - - final knownSubspaces = _renderKnownSubspaces( - context, - canLinkSpace, - spaceIdOrAlias, - spaces, - // crossAxisCount: crossAxisCount, - ); - - final moreSubspaces = spaces.hasMore - ? renderMoreSubspaces( - context, - ref, - spaceIdOrAlias, - ) - : null; - - final items = [ - if (knownSubspaces != null) ...knownSubspaces, - if (moreSubspaces != null) moreSubspaces, - ]; - - if (items.isEmpty) return null; - if (titleBuilder != null) { - final title = titleBuilder(); - if (title != null) { - items.insert(0, title); - } - } - return SingleChildScrollView( - child: Column(children: items), - ); -} From 4e9be4a408a451846a32447eb32708e58b7e712b Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 13:46:26 +0530 Subject: [PATCH 49/57] Added RoomCard menu options --- app/lib/features/spaces/pages/sub_spaces.dart | 34 +++++++++++++++---- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 19f814b7119e..bdc5eb45f95c 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,6 +1,8 @@ import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/room/room_card.dart'; +import 'package:acter/common/widgets/room/room_hierarchy_options_menu.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; @@ -146,7 +148,7 @@ class SubSpaces extends ConsumerWidget { shrinkWrap: true, itemCount: categoryList.length, itemBuilder: (BuildContext context, int index) { - return _buildCategoriesList(context, categoryList[index]); + return _buildCategoriesList(context, ref, categoryList[index]); }, ); }, @@ -160,9 +162,20 @@ class SubSpaces extends ConsumerWidget { Widget _buildCategoriesList( BuildContext context, + WidgetRef ref, CategoryModelLocal categoryModelLocal, ) { final entries = categoryModelLocal.entries; + + final suggestedSpaces = + ref.watch(suggestedSpacesProvider(spaceId)).valueOrNull; + final suggestedSpaceIds = []; + if (suggestedSpaces != null && + (suggestedSpaces.$1.isNotEmpty || suggestedSpaces.$2.isNotEmpty)) { + suggestedSpaceIds.addAll(suggestedSpaces.$1); + suggestedSpaceIds.addAll(suggestedSpaces.$2); + } + return Card( child: ExpansionTile( tilePadding: const EdgeInsets.only(right: 16), @@ -170,15 +183,22 @@ class SubSpaces extends ConsumerWidget { shape: const Border(), collapsedBackgroundColor: Colors.transparent, title: CategoryHeaderView(categoryModelLocal: categoryModelLocal), - children: List.generate( - entries.length, - (index) => RoomCard( - roomId: entries[index], + children: List.generate(entries.length, (index) { + final roomId = entries[index]; + final isSuggested = suggestedSpaceIds.contains(roomId); + return RoomCard( + roomId: roomId, showParents: false, showVisibilityMark: true, + showSuggestedMark: isSuggested, + trailing: RoomHierarchyOptionsMenu( + childId: roomId, + parentId: spaceId, + isSuggested: isSuggested, + ), margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), - ), - ), + ); + }), ), ); } From 6fcf12dd1c83f9f89c7f1fc6d6f1dc5b6128c9c2 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Wed, 18 Sep 2024 13:51:12 +0530 Subject: [PATCH 50/57] Added entries at begin which are came from delete category item --- app/lib/features/categories/organize_categories_page.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/lib/features/categories/organize_categories_page.dart b/app/lib/features/categories/organize_categories_page.dart index 990c0252d7ac..6d26ebac628d 100644 --- a/app/lib/features/categories/organize_categories_page.dart +++ b/app/lib/features/categories/organize_categories_page.dart @@ -104,7 +104,7 @@ class _DraggableCategoriesListState void callDeleteCategory(int categoryIndex) async { List entriesOfDeleteCategory = categoryList[categoryIndex].entries; CategoryModelLocal unCategoriesItem = categoryList[categoryList.length - 1]; - unCategoriesItem.entries.addAll(entriesOfDeleteCategory); + unCategoriesItem.entries.insertAll(0, entriesOfDeleteCategory); categoryList.removeAt(categoryIndex); categoryList.removeAt(categoryList.length - 1); categoryList.add(unCategoriesItem); From 84653d6d8c9b0fe10f99c959c2b335506afc0dc7 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 11:51:43 +0530 Subject: [PATCH 51/57] Make sub-chats with categories options --- app/lib/common/utils/routes.dart | 2 +- .../providers/categories_providers.dart | 15 +- .../categories/utils/category_utils.dart | 2 +- .../features/chat/pages/sub_chats_page.dart | 205 ++++++++++++++++++ .../chat/providers/chat_providers.dart | 20 ++ app/lib/features/space/pages/chats_page.dart | 165 -------------- .../widgets/space_sections/chats_section.dart | 4 +- app/lib/features/spaces/pages/sub_spaces.dart | 2 +- .../shell_routers/home_shell_router.dart | 28 +-- 9 files changed, 256 insertions(+), 187 deletions(-) create mode 100644 app/lib/features/chat/pages/sub_chats_page.dart delete mode 100644 app/lib/features/space/pages/chats_page.dart diff --git a/app/lib/common/utils/routes.dart b/app/lib/common/utils/routes.dart index 7b9414530f1a..2d4c31bb9b2e 100644 --- a/app/lib/common/utils/routes.dart +++ b/app/lib/common/utils/routes.dart @@ -66,11 +66,11 @@ enum Routes { spaceInvite('/:spaceId([!#][^/]+)/invite'), space('/:spaceId([!#][^/]+)'), // !spaceId, #spaceName subSpaces('/:spaceId([!#][^/]+)/subSpaces'), + subChats('/:spaceId([!#][^/]+)/subChats'), organizeCategories('/organizeCategories/:spaceId([^/]+)/:categoriesFor([^/]+)'), spaceMembers('/:spaceId([!#][^/]+)/members'), spacePins('/:spaceId([!#][^/]+)/pins'), spaceEvents('/:spaceId([!#][^/]+)/events'), - spaceChats('/:spaceId([!#][^/]+)/chats'), spaceTasks('/:spaceId([!#][^/]+)/tasks'), // -- space Settings spaceSettings('/:spaceId([!#][^/]+)/settings'), diff --git a/app/lib/features/categories/providers/categories_providers.dart b/app/lib/features/categories/providers/categories_providers.dart index 45956d12ce22..82d365019018 100644 --- a/app/lib/features/categories/providers/categories_providers.dart +++ b/app/lib/features/categories/providers/categories_providers.dart @@ -1,6 +1,7 @@ import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/features/categories/model/CategoryModelLocal.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; +import 'package:acter/features/chat/providers/chat_providers.dart'; import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -30,11 +31,19 @@ final localCategoryListProvider = FutureProvider.family ), ).future, ); - final subSpacesList = - await ref.read(subSpacesListProvider(categoryInfo.spaceId).future); + List subEntriesList = []; + + if (categoryInfo.categoriesFor == CategoriesFor.spaces) { + subEntriesList = + await ref.read(subSpacesListProvider(categoryInfo.spaceId).future); + } else if (categoryInfo.categoriesFor == CategoriesFor.chats) { + subEntriesList = + await ref.read(subChatsListProvider(categoryInfo.spaceId).future); + } + final categoryList = CategoryUtils().getCategorisedList( categoriesManager.categories().toList(), - subSpacesList, + subEntriesList, ); return categoryList; }); diff --git a/app/lib/features/categories/utils/category_utils.dart b/app/lib/features/categories/utils/category_utils.dart index 8999ae451b0e..d0040b98c0d5 100644 --- a/app/lib/features/categories/utils/category_utils.dart +++ b/app/lib/features/categories/utils/category_utils.dart @@ -26,7 +26,7 @@ class CategoryUtils { } ///GET LIST OF LOCAL CATEGORY WHICH EXCLUDE ITEM WITH EMPTY ENTRIES - List getCategorisedSubSpacesWithoutEmptyList( + List getCategorisedListWithoutEmptyEntries( List categoryList, ) { List categoryListLocalWithoutEmptyEntries = []; diff --git a/app/lib/features/chat/pages/sub_chats_page.dart b/app/lib/features/chat/pages/sub_chats_page.dart new file mode 100644 index 000000000000..574dcab91778 --- /dev/null +++ b/app/lib/features/chat/pages/sub_chats_page.dart @@ -0,0 +1,205 @@ +import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/common/utils/routes.dart'; +import 'package:acter/common/widgets/room/room_card.dart'; +import 'package:acter/common/widgets/room/room_hierarchy_options_menu.dart'; +import 'package:acter/features/categories/model/CategoryModelLocal.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/categories/utils/category_utils.dart'; +import 'package:acter/features/categories/widgets/category_header_view.dart'; +import 'package:acter/features/chat/providers/chat_providers.dart'; +import 'package:atlas_icons/atlas_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; +import 'package:logging/logging.dart'; +import 'package:phosphor_flutter/phosphor_flutter.dart'; + +final _log = Logger('a3::space::sub_chats'); + +class SubChatsPage extends ConsumerWidget { + static const moreOptionKey = Key('sub-chats-more-actions'); + static const createSubChatKey = Key('sub-chats-more-create-subChat'); + static const linkSubChatKey = Key('sub-chats-more-link-subChat'); + final String spaceId; + + const SubChatsPage({super.key, required this.spaceId}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Scaffold( + appBar: _buildAppBarUI(context, ref), + body: _buildSubChatsUI(context, ref), + ); + } + + AppBar _buildAppBarUI(BuildContext context, WidgetRef ref) { + final spaceName = ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull; + final membership = ref.watch(roomMembershipProvider(spaceId)); + bool canLinkSpace = + membership.valueOrNull?.canString('CanLinkSpaces') == true; + return AppBar( + centerTitle: false, + title: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(L10n.of(context).chats), + Text( + '($spaceName)', + overflow: TextOverflow.ellipsis, + style: Theme.of(context).textTheme.labelLarge, + ), + ], + ), + actions: [ + IconButton( + icon: Icon(PhosphorIcons.arrowsClockwise()), + onPressed: () => ref.invalidate(subChatsListProvider), + ), + if (canLinkSpace) _buildMenuOptions(context), + ], + ); + } + + Widget _buildMenuOptions(BuildContext context) { + return PopupMenuButton( + icon: Icon(PhosphorIcons.dotsThreeVertical()), + iconSize: 28, + color: Theme.of(context).colorScheme.surface, + itemBuilder: (BuildContext context) => [ + PopupMenuItem( + key: SubChatsPage.createSubChatKey, + onTap: () => context.pushNamed( + Routes.createSpace.name, + queryParameters: {'parentSpaceId': spaceId}, + ), + child: Row( + children: [ + Icon(PhosphorIcons.plus()), + const SizedBox(width: 6), + Text(L10n.of(context).createSubspace), + ], + ), + ), + PopupMenuItem( + key: SubChatsPage.linkSubChatKey, + onTap: () => context.pushNamed( + Routes.linkSubspace.name, + pathParameters: {'spaceId': spaceId}, + ), + child: Row( + children: [ + Icon(PhosphorIcons.link()), + const SizedBox(width: 6), + Text(L10n.of(context).linkExistingSpace), + ], + ), + ), + PopupMenuItem( + onTap: () => context.pushNamed( + Routes.linkRecommended.name, + pathParameters: {'spaceId': spaceId}, + ), + child: Row( + children: [ + const Icon(Atlas.link_select, size: 18), + const SizedBox(width: 8), + Text(L10n.of(context).recommendedSpaces), + ], + ), + ), + PopupMenuItem( + onTap: () => context.pushNamed( + Routes.organizeCategories.name, + pathParameters: { + 'spaceId': spaceId, + 'categoriesFor': CategoriesFor.chats.name, + }, + ), + child: Row( + children: [ + Icon(PhosphorIcons.dotsSixVertical()), + const SizedBox(width: 6), + Text(L10n.of(context).organize), + ], + ), + ), + ], + ); + } + + Widget _buildSubChatsUI(BuildContext context, WidgetRef ref) { + final localCategoryList = ref.watch( + localCategoryListProvider( + ( + spaceId: spaceId, + categoriesFor: CategoriesFor.chats, + ), + ), + ); + + return localCategoryList.when( + data: (localCategoryListData) { + final categoryList = CategoryUtils() + .getCategorisedListWithoutEmptyEntries(localCategoryListData); + return ListView.builder( + scrollDirection: Axis.vertical, + shrinkWrap: true, + itemCount: categoryList.length, + itemBuilder: (BuildContext context, int index) { + return _buildCategoriesList(context, ref, categoryList[index]); + }, + ); + }, + error: (e, s) { + _log.severe('Failed to load the sub-spaces', e, s); + return Center(child: Text(L10n.of(context).loadingFailed(e))); + }, + loading: () => Center(child: Text(L10n.of(context).loading)), + ); + } + + Widget _buildCategoriesList( + BuildContext context, + WidgetRef ref, + CategoryModelLocal categoryModelLocal, + ) { + final entries = categoryModelLocal.entries; + + final suggestedChats = + ref.watch(suggestedChatsProvider(spaceId)).valueOrNull; + final suggestedChatIds = []; + if (suggestedChats != null && + (suggestedChats.$1.isNotEmpty || suggestedChats.$2.isNotEmpty)) { + suggestedChatIds.addAll(suggestedChats.$1); + suggestedChatIds.addAll(suggestedChats.$2); + } + + return Card( + child: ExpansionTile( + tilePadding: const EdgeInsets.only(right: 16), + initiallyExpanded: true, + shape: const Border(), + collapsedBackgroundColor: Colors.transparent, + title: CategoryHeaderView(categoryModelLocal: categoryModelLocal), + children: List.generate(entries.length, (index) { + final roomId = entries[index]; + final isSuggested = suggestedChatIds.contains(roomId); + return RoomCard( + roomId: roomId, + showParents: false, + showVisibilityMark: true, + showSuggestedMark: isSuggested, + trailing: RoomHierarchyOptionsMenu( + childId: roomId, + parentId: spaceId, + isSuggested: isSuggested, + ), + margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), + ); + }), + ), + ); + } +} diff --git a/app/lib/features/chat/providers/chat_providers.dart b/app/lib/features/chat/providers/chat_providers.dart index 2502d9eb01bb..ec34a3d5d211 100644 --- a/app/lib/features/chat/providers/chat_providers.dart +++ b/app/lib/features/chat/providers/chat_providers.dart @@ -3,6 +3,7 @@ import 'package:acter/common/providers/chat_providers.dart'; import 'package:acter/common/providers/common_providers.dart'; import 'package:acter/common/providers/network_provider.dart'; import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/providers/space_providers.dart'; import 'package:acter/common/utils/utils.dart'; import 'package:acter/features/chat/models/chat_input_state/chat_input_state.dart'; import 'package:acter/features/chat/models/chat_room_state/chat_room_state.dart'; @@ -250,3 +251,22 @@ final hasUnreadChatsProvider = FutureProvider.autoDispose((ref) async { } return currentBadge; }); + +final subChatsListProvider = +FutureProvider.family, String>((ref, spaceId) async { + List subChatsList = []; + + //Get known sub-chats + final spaceRelationsOverview = + await ref.watch(spaceRelationsOverviewProvider(spaceId).future); + subChatsList.addAll(spaceRelationsOverview.knownChats); + + //Get more sub-chats + final relatedChatsLoader = + await ref.watch(remoteChatRelationsProvider(spaceId).future); + for (var element in relatedChatsLoader) { + subChatsList.add(element.roomIdStr()); + } + + return subChatsList; +}); diff --git a/app/lib/features/space/pages/chats_page.dart b/app/lib/features/space/pages/chats_page.dart deleted file mode 100644 index ea7a46f4454d..000000000000 --- a/app/lib/features/space/pages/chats_page.dart +++ /dev/null @@ -1,165 +0,0 @@ -import 'package:acter/common/providers/room_providers.dart'; -import 'package:acter/common/providers/space_providers.dart'; -import 'package:acter/common/toolkit/buttons/inline_text_button.dart'; -import 'package:acter/common/toolkit/buttons/primary_action_button.dart'; -import 'package:acter/common/utils/routes.dart'; -import 'package:acter/features/space/widgets/loading_convo_card.dart'; -import 'package:acter/common/widgets/empty_state_widget.dart'; -import 'package:acter/features/space/widgets/related/chats_helpers.dart'; -import 'package:atlas_icons/atlas_icons.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_gen/gen_l10n/l10n.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -class SpaceChatsPage extends ConsumerWidget { - static const createChatKey = Key('space-chat-create'); - static const actionsMenuKey = Key('space-chat-actions-menu'); - final String spaceIdOrAlias; - - const SpaceChatsPage({super.key, required this.spaceIdOrAlias}); - - Widget _renderLoading(BuildContext context) { - return ListView.builder( - shrinkWrap: true, - itemCount: 3, - itemBuilder: (context, idx) => const LoadingConvoCard(roomId: 'fake'), - ); - } - - Widget _renderEmpty(BuildContext context, WidgetRef ref) { - final membership = ref.watch(roomMembershipProvider(spaceIdOrAlias)); - bool canCreateSpace = - membership.valueOrNull?.canString('CanLinkSpaces') == true; - - return Center( - heightFactor: 1, - child: EmptyState( - title: L10n.of(context).noChatsInThisSpaceYet, - subtitle: L10n.of(context).getConversationGoingToStart, - image: 'assets/images/empty_chat.svg', - primaryButton: canCreateSpace - ? ActerPrimaryActionButton( - onPressed: () => context.pushNamed( - Routes.createChat.name, - queryParameters: {'spaceId': spaceIdOrAlias}, - extra: 1, - ), - child: Text(L10n.of(context).createSpaceChat), - ) - : null, - secondaryButton: canCreateSpace - ? ActerInlineTextButton( - onPressed: () => context.pushNamed( - Routes.linkChat.name, - pathParameters: {'spaceId': spaceIdOrAlias}, - ), - child: Text(L10n.of(context).linkToChat), - ) - : null, - ), - ); - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - final spaceName = - ref.watch(roomDisplayNameProvider(spaceIdOrAlias)).valueOrNull ?? - spaceIdOrAlias; - - final chatListAsync = - ref.watch(spaceRelationsOverviewProvider(spaceIdOrAlias)); - final chatList = chatListAsync.valueOrNull?.knownChats ?? []; - final remoteChatsAsync = - ref.watch(remoteChatRelationsProvider(spaceIdOrAlias)); - final remoteChats = remoteChatsAsync.valueOrNull ?? []; - final isLoading = chatListAsync.isLoading || remoteChatsAsync.isLoading; - final isEmpty = (chatListAsync.hasValue ? chatList.isEmpty : false) && - (remoteChatsAsync.hasValue ? remoteChats.isEmpty : false); - - final membership = ref.watch(roomMembershipProvider(spaceIdOrAlias)); - bool canCreateSpace = - membership.valueOrNull?.canString('CanLinkSpaces') == true; - - return Scaffold( - appBar: AppBar( - title: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text(L10n.of(context).chat), - Text( - '($spaceName)', - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.labelLarge, - ), - ], - ), - actions: [ - IconButton( - icon: const Icon(Atlas.arrows_rotating_right_thin), - iconSize: 28, - color: Theme.of(context).colorScheme.surface, - onPressed: () async { - ref.invalidate(spaceRelationsProvider); - }, - ), - if (canCreateSpace) - PopupMenuButton( - key: actionsMenuKey, - icon: const Icon(Atlas.plus_circle), - iconSize: 28, - color: Theme.of(context).colorScheme.surface, - itemBuilder: (BuildContext context) => [ - PopupMenuItem( - key: createChatKey, - onTap: () => context.pushNamed( - Routes.createChat.name, - queryParameters: {'spaceId': spaceIdOrAlias}, - extra: 1, - ), - child: Row( - children: [ - Text(L10n.of(context).createChat), - const Spacer(), - const Icon(Atlas.chats), - ], - ), - ), - PopupMenuItem( - onTap: () => context.pushNamed( - Routes.linkChat.name, - pathParameters: {'spaceId': spaceIdOrAlias}, - ), - child: Row( - children: [ - Text(L10n.of(context).linkExistingChat), - const Spacer(), - const Icon(Atlas.chats), - ], - ), - ), - ], - ), - ], - ), - body: SingleChildScrollView( - child: Column( - children: [ - if (chatList.isNotEmpty) - chatsListUI( - ref, - spaceIdOrAlias, - chatList, - chatList.length, - showOptions: true, - ), - if (isLoading) _renderLoading(context), - if (remoteChats.isNotEmpty) - renderFurther(context, ref, spaceIdOrAlias, null), - if (isEmpty) _renderEmpty(context, ref), - ], - ), - ), - ); - } -} diff --git a/app/lib/features/space/widgets/space_sections/chats_section.dart b/app/lib/features/space/widgets/space_sections/chats_section.dart index 8fab8a725857..9413420fb7d2 100644 --- a/app/lib/features/space/widgets/space_sections/chats_section.dart +++ b/app/lib/features/space/widgets/space_sections/chats_section.dart @@ -76,7 +76,7 @@ class ChatsSection extends ConsumerWidget { title: L10n.of(context).suggestedChats, isShowSeeAllButton: true, onTapSeeAll: () => context.pushNamed( - Routes.spaceChats.name, + Routes.subChats.name, pathParameters: {'spaceId': spaceId}, ), ), @@ -122,7 +122,7 @@ class ChatsSection extends ConsumerWidget { title: L10n.of(context).chats, isShowSeeAllButton: config.isShowSeeAllButton, onTapSeeAll: () => context.pushNamed( - Routes.spaceChats.name, + Routes.subChats.name, pathParameters: {'spaceId': spaceId}, ), ), diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index bdc5eb45f95c..987df12d671d 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -142,7 +142,7 @@ class SubSpaces extends ConsumerWidget { return localCategoryList.when( data: (localCategoryListData) { final categoryList = CategoryUtils() - .getCategorisedSubSpacesWithoutEmptyList(localCategoryListData); + .getCategorisedListWithoutEmptyEntries(localCategoryListData); return ListView.builder( scrollDirection: Axis.vertical, shrinkWrap: true, diff --git a/app/lib/router/shell_routers/home_shell_router.dart b/app/lib/router/shell_routers/home_shell_router.dart index af04c762486f..cd8fbae42f84 100644 --- a/app/lib/router/shell_routers/home_shell_router.dart +++ b/app/lib/router/shell_routers/home_shell_router.dart @@ -2,6 +2,7 @@ import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/with_sidebar.dart'; import 'package:acter/features/categories/organize_categories_page.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; +import 'package:acter/features/chat/pages/sub_chats_page.dart'; import 'package:acter/features/events/pages/create_event_page.dart'; import 'package:acter/features/events/pages/event_list_page.dart'; import 'package:acter/features/invite_members/pages/invite_individual_users.dart'; @@ -31,7 +32,6 @@ import 'package:acter/features/space/settings/pages/visibility_accessibility_pag import 'package:acter/features/space/settings/widgets/space_settings_menu.dart'; import 'package:acter/features/spaces/pages/sub_spaces.dart'; import 'package:acter/features/super_invites/pages/super_invites.dart'; -import 'package:acter/features/space/pages/chats_page.dart'; import 'package:acter/features/space/pages/members_page.dart'; import 'package:acter/features/space/settings/pages/apps_settings_page.dart'; import 'package:acter/features/space/settings/pages/index_page.dart'; @@ -227,6 +227,19 @@ final homeShellRoutes = [ ); }, ), + GoRoute( + name: Routes.subChats.name, + path: Routes.subChats.route, + redirect: authGuardRedirect, + pageBuilder: (context, state) { + return NoTransitionPage( + key: state.pageKey, + child: SubChatsPage( + spaceId: state.pathParameters['spaceId']!, + ), + ); + }, + ), GoRoute( name: Routes.organizeCategories.name, path: Routes.organizeCategories.route, @@ -281,19 +294,6 @@ final homeShellRoutes = [ ); }, ), - GoRoute( - name: Routes.spaceChats.name, - path: Routes.spaceChats.route, - redirect: authGuardRedirect, - pageBuilder: (context, state) { - return NoTransitionPage( - key: state.pageKey, - child: SpaceChatsPage( - spaceIdOrAlias: state.pathParameters['spaceId']!, - ), - ); - }, - ), GoRoute( name: Routes.spaceTasks.name, path: Routes.spaceTasks.route, From 946368c04bbfdb8a74532ce7f52d4b95fcdf9072 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 12:00:13 +0530 Subject: [PATCH 52/57] Minor fixes --- .../features/chat/pages/sub_chats_page.dart | 22 ++++--------------- 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/app/lib/features/chat/pages/sub_chats_page.dart b/app/lib/features/chat/pages/sub_chats_page.dart index 574dcab91778..bd2b64b98688 100644 --- a/app/lib/features/chat/pages/sub_chats_page.dart +++ b/app/lib/features/chat/pages/sub_chats_page.dart @@ -8,7 +8,6 @@ import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter/features/chat/providers/chat_providers.dart'; -import 'package:atlas_icons/atlas_icons.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -71,41 +70,28 @@ class SubChatsPage extends ConsumerWidget { PopupMenuItem( key: SubChatsPage.createSubChatKey, onTap: () => context.pushNamed( - Routes.createSpace.name, + Routes.createChat.name, queryParameters: {'parentSpaceId': spaceId}, ), child: Row( children: [ Icon(PhosphorIcons.plus()), const SizedBox(width: 6), - Text(L10n.of(context).createSubspace), + Text(L10n.of(context).createChat), ], ), ), PopupMenuItem( key: SubChatsPage.linkSubChatKey, onTap: () => context.pushNamed( - Routes.linkSubspace.name, + Routes.linkChat.name, pathParameters: {'spaceId': spaceId}, ), child: Row( children: [ Icon(PhosphorIcons.link()), const SizedBox(width: 6), - Text(L10n.of(context).linkExistingSpace), - ], - ), - ), - PopupMenuItem( - onTap: () => context.pushNamed( - Routes.linkRecommended.name, - pathParameters: {'spaceId': spaceId}, - ), - child: Row( - children: [ - const Icon(Atlas.link_select, size: 18), - const SizedBox(width: 8), - Text(L10n.of(context).recommendedSpaces), + Text(L10n.of(context).linkExistingChat), ], ), ), From 23312399834dee380bf83799c22d2b07bd9cbc4e Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 12:12:49 +0530 Subject: [PATCH 53/57] Change related to providers updates --- .../features/chat/pages/sub_chats_page.dart | 5 ++++- .../space/sheets/link_room_sheet.dart | 20 ++++++++++++++++--- app/lib/features/spaces/pages/sub_spaces.dart | 5 ++++- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/app/lib/features/chat/pages/sub_chats_page.dart b/app/lib/features/chat/pages/sub_chats_page.dart index bd2b64b98688..a18af4c8dba3 100644 --- a/app/lib/features/chat/pages/sub_chats_page.dart +++ b/app/lib/features/chat/pages/sub_chats_page.dart @@ -54,7 +54,10 @@ class SubChatsPage extends ConsumerWidget { actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () => ref.invalidate(subChatsListProvider), + onPressed: () { + ref.invalidate(subChatsListProvider); + ref.invalidate(localCategoryListProvider); + }, ), if (canLinkSpace) _buildMenuOptions(context), ], diff --git a/app/lib/features/space/sheets/link_room_sheet.dart b/app/lib/features/space/sheets/link_room_sheet.dart index c6a97b2efc55..ea5de98eb2bd 100644 --- a/app/lib/features/space/sheets/link_room_sheet.dart +++ b/app/lib/features/space/sheets/link_room_sheet.dart @@ -8,8 +8,11 @@ import 'package:acter/common/utils/utils.dart'; import 'package:acter/common/widgets/room/brief_room_list_entry.dart'; import 'package:acter/common/widgets/search.dart'; import 'package:acter/common/widgets/sliver_scaffold.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; +import 'package:acter/features/chat/providers/chat_providers.dart'; import 'package:acter/features/home/widgets/space_chip.dart'; import 'package:acter/features/space/actions/unlink_child_room.dart'; +import 'package:acter/features/spaces/providers/space_list_provider.dart'; import 'package:acter_avatar/acter_avatar.dart'; import 'package:acter_flutter_sdk/acter_flutter_sdk_ffi.dart'; import 'package:flutter/material.dart'; @@ -417,9 +420,8 @@ class _LinkRoomPageConsumerState extends ConsumerState { } else { childRoomsIds.add(roomId); } - // spaceRelations come from the server and must be manually invalidated - ref.invalidate(spaceRelationsProvider(selectedParentSpaceId)); - ref.invalidate(spaceRemoteRelationsProvider(selectedParentSpaceId)); + + invalidateProviders(selectedParentSpaceId); } //Unlink child room @@ -439,5 +441,17 @@ class _LinkRoomPageConsumerState extends ConsumerState { } else { childRoomsIds.remove(roomId); } + + //Invalidate providers + invalidateProviders(selectedParentSpaceId); + } + + void invalidateProviders(String selectedParentSpaceId) { + //Invalidate providers + ref.invalidate(spaceRelationsProvider(selectedParentSpaceId)); + ref.invalidate(spaceRemoteRelationsProvider(selectedParentSpaceId)); + ref.invalidate(subChatsListProvider(selectedParentSpaceId)); + ref.invalidate(subSpacesListProvider(selectedParentSpaceId)); + ref.invalidate(localCategoryListProvider); } } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index 987df12d671d..a8e90982c377 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -55,7 +55,10 @@ class SubSpaces extends ConsumerWidget { actions: [ IconButton( icon: Icon(PhosphorIcons.arrowsClockwise()), - onPressed: () => ref.invalidate(subSpacesListProvider), + onPressed: () { + ref.invalidate(subSpacesListProvider); + ref.invalidate(localCategoryListProvider); + }, ), if (canLinkSpace) _buildMenuOptions(context), ], From 6286083b65272b7db043ec7d987d733d389cc039 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 12:19:01 +0530 Subject: [PATCH 54/57] Added skeleton loading UI --- .../general_list_skeleton_widget.dart | 56 +++++++++++++++++++ .../features/chat/pages/sub_chats_page.dart | 3 +- app/lib/features/spaces/pages/sub_spaces.dart | 3 +- 3 files changed, 60 insertions(+), 2 deletions(-) create mode 100644 app/lib/common/skeletons/general_list_skeleton_widget.dart diff --git a/app/lib/common/skeletons/general_list_skeleton_widget.dart b/app/lib/common/skeletons/general_list_skeleton_widget.dart new file mode 100644 index 000000000000..16bb6bce5e82 --- /dev/null +++ b/app/lib/common/skeletons/general_list_skeleton_widget.dart @@ -0,0 +1,56 @@ +import 'package:atlas_icons/atlas_icons.dart'; +import 'package:flutter/material.dart'; +import 'package:skeletonizer/skeletonizer.dart'; +import 'package:flutter_gen/gen_l10n/l10n.dart'; + +class GeneralListSkeletonWidget extends StatelessWidget { + const GeneralListSkeletonWidget({super.key}); + + @override + Widget build(BuildContext context) { + return Skeletonizer(child: _buildSkeletonUI(context)); + } + + Widget _buildSkeletonUI(BuildContext context) { + return Column( + children: [ + _buildListItemSkeletonUI(context), + _buildListItemSkeletonUI(context), + _buildListItemSkeletonUI(context), + _buildListItemSkeletonUI(context), + _buildListItemSkeletonUI(context), + ], + ); + } + + Widget _buildListItemSkeletonUI(BuildContext context) { + return Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Container( + height: 50, + width: 50, + color: Colors.white, + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(L10n.of(context).title + L10n.of(context).title), + Text( + L10n.of(context).description + L10n.of(context).description, + ), + ], + ), + ), + const SizedBox(width: 20), + const Icon(Atlas.crown_winner_thin), + const SizedBox(width: 10), + const Icon(Atlas.dots_vertical), + ], + ), + ); + } +} diff --git a/app/lib/features/chat/pages/sub_chats_page.dart b/app/lib/features/chat/pages/sub_chats_page.dart index a18af4c8dba3..b07569906802 100644 --- a/app/lib/features/chat/pages/sub_chats_page.dart +++ b/app/lib/features/chat/pages/sub_chats_page.dart @@ -1,5 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/common/skeletons/general_list_skeleton_widget.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/room/room_card.dart'; import 'package:acter/common/widgets/room/room_hierarchy_options_menu.dart'; @@ -145,7 +146,7 @@ class SubChatsPage extends ConsumerWidget { _log.severe('Failed to load the sub-spaces', e, s); return Center(child: Text(L10n.of(context).loadingFailed(e))); }, - loading: () => Center(child: Text(L10n.of(context).loading)), + loading: () => const GeneralListSkeletonWidget(), ); } diff --git a/app/lib/features/spaces/pages/sub_spaces.dart b/app/lib/features/spaces/pages/sub_spaces.dart index a8e90982c377..fcd6de84e8a3 100644 --- a/app/lib/features/spaces/pages/sub_spaces.dart +++ b/app/lib/features/spaces/pages/sub_spaces.dart @@ -1,5 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/common/skeletons/general_list_skeleton_widget.dart'; import 'package:acter/common/utils/routes.dart'; import 'package:acter/common/widgets/room/room_card.dart'; import 'package:acter/common/widgets/room/room_hierarchy_options_menu.dart'; @@ -159,7 +160,7 @@ class SubSpaces extends ConsumerWidget { _log.severe('Failed to load the sub-spaces', e, s); return Center(child: Text(L10n.of(context).loadingFailed(e))); }, - loading: () => Center(child: Text(L10n.of(context).loading)), + loading: () => const GeneralListSkeletonWidget(), ); } From 28959d2390bfb213d55017874e4591a293575bfe Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 13:41:11 +0530 Subject: [PATCH 55/57] Minor fixes --- app/lib/features/space/actions/unlink_child_room.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/lib/features/space/actions/unlink_child_room.dart b/app/lib/features/space/actions/unlink_child_room.dart index 35d974833097..a93fe719a62b 100644 --- a/app/lib/features/space/actions/unlink_child_room.dart +++ b/app/lib/features/space/actions/unlink_child_room.dart @@ -1,5 +1,6 @@ import 'package:acter/common/providers/room_providers.dart'; import 'package:acter/common/providers/space_providers.dart'; +import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:flutter/widgets.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -25,4 +26,5 @@ Future unlinkChildRoom( // spaceRelations come from the server and must be manually invalidated ref.invalidate(spaceRelationsProvider(parentId)); ref.invalidate(spaceRemoteRelationsProvider(parentId)); + ref.invalidate(localCategoryListProvider); } From e36e3fa508d4d482b171edb36fdf390db4bcf648 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 14:23:56 +0530 Subject: [PATCH 56/57] Updated change log data --- .changes/2168-categorized-structure.md | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .changes/2168-categorized-structure.md diff --git a/.changes/2168-categorized-structure.md b/.changes/2168-categorized-structure.md new file mode 100644 index 000000000000..e62716dfda0b --- /dev/null +++ b/.changes/2168-categorized-structure.md @@ -0,0 +1,2 @@ +- [New] : All new categorize management for sub-spaces and sub-chats +- [New] : You can now create custom categories and manage all the sub-space and sub-chat base on the your requirements \ No newline at end of file From 975d5588921421d926d272836c07197691e33832 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Fri, 20 Sep 2024 16:21:06 +0530 Subject: [PATCH 57/57] Added missing Goto chat call on tap of Chat Room Card --- app/lib/features/chat/pages/sub_chats_page.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/lib/features/chat/pages/sub_chats_page.dart b/app/lib/features/chat/pages/sub_chats_page.dart index b07569906802..ecac40e1f810 100644 --- a/app/lib/features/chat/pages/sub_chats_page.dart +++ b/app/lib/features/chat/pages/sub_chats_page.dart @@ -9,6 +9,7 @@ import 'package:acter/features/categories/providers/categories_providers.dart'; import 'package:acter/features/categories/utils/category_utils.dart'; import 'package:acter/features/categories/widgets/category_header_view.dart'; import 'package:acter/features/chat/providers/chat_providers.dart'; +import 'package:acter/router/utils.dart'; import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -186,6 +187,7 @@ class SubChatsPage extends ConsumerWidget { parentId: spaceId, isSuggested: isSuggested, ), + onTap: () => goToChat(context, roomId), margin: const EdgeInsets.symmetric(vertical: 2, horizontal: 8), ); }),