From 9cd7e1452de80a5048a4068ae885483733b3f278 Mon Sep 17 00:00:00 2001 From: kumarpalsinh25 Date: Thu, 15 Aug 2024 19:51:02 +0530 Subject: [PATCH] Pin Details Page : Added Pin Content Views and Delete old pin page class --- app/integration_test/tests/pins.dart | 16 +- app/lib/common/widgets/space_name_widget.dart | 15 +- .../events/pages/event_list_page.dart | 2 +- app/lib/features/home/widgets/space_chip.dart | 2 +- .../features/pins/pages/pin_details_page.dart | 127 +++++++- app/lib/features/pins/pages/pin_page.dart | 278 ------------------ .../features/pins/pages/pins_list_page.dart | 2 +- .../features/tasks/pages/tasks_list_page.dart | 2 +- app/lib/l10n/app_en.arb | 3 +- 9 files changed, 149 insertions(+), 298 deletions(-) delete mode 100644 app/lib/features/pins/pages/pin_page.dart diff --git a/app/integration_test/tests/pins.dart b/app/integration_test/tests/pins.dart index b77795a216d5..ea31515cfc88 100644 --- a/app/integration_test/tests/pins.dart +++ b/app/integration_test/tests/pins.dart @@ -3,7 +3,7 @@ import 'package:acter/common/widgets/html_editor.dart'; import 'package:acter/common/widgets/spaces/select_space_form_field.dart'; import 'package:acter/features/home/data/keys.dart'; import 'package:acter/features/pins/pages/create_pin_page.dart'; -import 'package:acter/features/pins/pages/pin_page.dart'; +import 'package:acter/features/pins/pages/pin_details_page.dart'; import 'package:acter/features/pins/widgets/pin_item.dart'; import 'package:acter/features/search/model/keys.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; @@ -74,15 +74,15 @@ extension ActerNews on ConvenientTest { } Future editPin(String title, String content, String url) async { - await find.byKey(PinPage.actionMenuKey).should(findsOneWidget); - final actionMenuKey = find.byKey(PinPage.actionMenuKey); + await find.byKey(PinDetailsPage.actionMenuKey).should(findsOneWidget); + final actionMenuKey = find.byKey(PinDetailsPage.actionMenuKey); await actionMenuKey.tap(); - await find.byKey(PinPage.editBtnKey).should(findsOneWidget); - final editBtnKey = find.byKey(PinPage.editBtnKey); + await find.byKey(PinDetailsPage.editBtnKey).should(findsOneWidget); + final editBtnKey = find.byKey(PinDetailsPage.editBtnKey); await editBtnKey.tap(); - final titleField = find.byKey(PinPage.titleFieldKey); + final titleField = find.byKey(PinDetailsPage.titleFieldKey); await titleField.should(findsOneWidget); await titleField.replaceText(title); @@ -109,9 +109,9 @@ extension ActerNews on ConvenientTest { await tester.ensureVisible(saveBtnKey); await saveBtnKey.tap(); - final pinPage = find.byKey(PinPage.pinPageKey); + final pinPage = find.byKey(PinDetailsPage.pinPageKey); await pinPage.should(findsOneWidget); - final page = pinPage.evaluate().first.widget as PinPage; + final page = pinPage.evaluate().first.widget as PinDetailsPage; return page.pinId; } } diff --git a/app/lib/common/widgets/space_name_widget.dart b/app/lib/common/widgets/space_name_widget.dart index d295af891796..f2688d3119b3 100644 --- a/app/lib/common/widgets/space_name_widget.dart +++ b/app/lib/common/widgets/space_name_widget.dart @@ -3,9 +3,14 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; class SpaceNameWidget extends ConsumerWidget { - final String? spaceId; + final String spaceId; + final bool isShowBrackets; - const SpaceNameWidget({super.key, this.spaceId}); + const SpaceNameWidget({ + super.key, + required this.spaceId, + this.isShowBrackets = true, + }); @override Widget build(BuildContext context, WidgetRef ref) { @@ -14,10 +19,12 @@ class SpaceNameWidget extends ConsumerWidget { Widget _buildSpaceName(BuildContext context, WidgetRef ref) { String spaceName = - ref.watch(roomDisplayNameProvider(spaceId!)).valueOrNull ?? ''; + ref.watch(roomDisplayNameProvider(spaceId)).valueOrNull ?? ''; + if (isShowBrackets) spaceName = '($spaceName)'; return Text( - '($spaceName)', + spaceName, overflow: TextOverflow.ellipsis, + maxLines: 3, style: Theme.of(context).textTheme.labelLarge, ); } diff --git a/app/lib/features/events/pages/event_list_page.dart b/app/lib/features/events/pages/event_list_page.dart index 89187a2f6436..2d06c9b900ad 100644 --- a/app/lib/features/events/pages/event_list_page.dart +++ b/app/lib/features/events/pages/event_list_page.dart @@ -54,7 +54,7 @@ class _EventListPageState extends ConsumerState { Text(L10n.of(context).events), if (widget.spaceId != null) SpaceNameWidget( - spaceId: widget.spaceId, + spaceId: widget.spaceId!, ), ], ), diff --git a/app/lib/features/home/widgets/space_chip.dart b/app/lib/features/home/widgets/space_chip.dart index 04347a31ca0b..663143a2525b 100644 --- a/app/lib/features/home/widgets/space_chip.dart +++ b/app/lib/features/home/widgets/space_chip.dart @@ -71,7 +71,7 @@ class SpaceChip extends ConsumerWidget { child: useCompatView ? Row( children: [ - const Text('In'), + Text(L10n.of(context).inKey), ActerInlineTextButton( onPressed: () => onTapSelectSpace != null ? onTapSelectSpace!() : null, diff --git a/app/lib/features/pins/pages/pin_details_page.dart b/app/lib/features/pins/pages/pin_details_page.dart index 1775d410d34f..fd4cb8aee37f 100644 --- a/app/lib/features/pins/pages/pin_details_page.dart +++ b/app/lib/features/pins/pages/pin_details_page.dart @@ -1,5 +1,11 @@ import 'package:acter/common/providers/common_providers.dart'; import 'package:acter/common/providers/room_providers.dart'; +import 'package:acter/common/widgets/edit_html_description_sheet.dart'; +import 'package:acter/common/widgets/render_html.dart'; +import 'package:acter/common/widgets/space_name_widget.dart'; +import 'package:acter/features/attachments/widgets/attachment_section.dart'; +import 'package:acter/features/comments/widgets/comments_section.dart'; +import 'package:acter/features/pins/Utils/pins_utils.dart'; import 'package:acter/features/pins/actions/edit_pin_actions.dart'; import 'package:acter/features/pins/actions/reduct_pin_action.dart'; import 'package:acter/features/pins/actions/report_pin_action.dart'; @@ -48,9 +54,18 @@ class _PinDetailsPageState extends ConsumerState { Widget _buildBodyUI() { final pinData = ref.watch(pinProvider(widget.pinId)); return pinData.when( - data: (pin) { - return Container(); - }, + data: (pin) => SingleChildScrollView( + child: Column( + children: [ + const SizedBox(height: 20), + _buildPinHeaderUI(pin), + const SizedBox(height: 20), + AttachmentSectionWidget(manager: pin.attachments()), + const SizedBox(height: 20), + CommentsSection(manager: pin.comments()), + ], + ), + ), loading: () => Skeletonizer(child: Text(L10n.of(context).loadingPin)), error: (err, st) => Text( L10n.of(context).errorLoadingPin(err), @@ -141,4 +156,110 @@ class _PinDetailsPageState extends ConsumerState { return actions; } + + Widget _buildPinHeaderUI(ActerPin pin) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + pinIconUI(), + const SizedBox(width: 12), + Expanded( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + pinTitleUI(pin), + pinSpaceNameUI(pin), + ], + ), + ), + ], + ), + const SizedBox(height: 18), + pinDescriptionUI(pin), + ], + ), + ); + } + + Widget pinIconUI() { + return Container( + height: 50, + width: 50, + decoration: BoxDecoration( + color: Theme.of(context).colorScheme.secondary, + borderRadius: const BorderRadius.all(Radius.circular(100)), + ), + child: const Icon(Atlas.pin), + ); + } + + Widget pinTitleUI(ActerPin pin) { + return Text( + pin.title(), + style: Theme.of(context).textTheme.titleSmall, + ); + } + + Widget pinSpaceNameUI(ActerPin pin) { + return Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + L10n.of(context).inKey, + style: Theme.of(context).textTheme.labelLarge, + ), + Text( + ' : ', + style: Theme.of(context).textTheme.labelLarge, + ), + Expanded( + child: SpaceNameWidget( + spaceId: pin.roomIdStr(), + isShowBrackets: false, + ), + ), + ], + ); + } + + Widget pinDescriptionUI(ActerPin pin) { + final description = pin.content(); + if (description == null) return const SizedBox.shrink(); + final formattedBody = description.formattedBody(); + + return SelectionArea( + child: GestureDetector( + onTap: () { + showEditHtmlDescriptionBottomSheet( + context: context, + descriptionHtmlValue: description.formattedBody(), + descriptionMarkdownValue: description.body(), + onSave: (htmlBodyDescription, plainDescription) async { + saveDescription( + context, + htmlBodyDescription, + plainDescription, + pin, + ); + }, + ); + }, + child: formattedBody != null + ? RenderHtml( + text: formattedBody, + defaultTextStyle: Theme.of(context).textTheme.labelLarge, + ) + : Text( + description.body(), + style: Theme.of(context).textTheme.labelLarge, + ), + ), + ); + } } diff --git a/app/lib/features/pins/pages/pin_page.dart b/app/lib/features/pins/pages/pin_page.dart deleted file mode 100644 index 63d8a86306bf..000000000000 --- a/app/lib/features/pins/pages/pin_page.dart +++ /dev/null @@ -1,278 +0,0 @@ -import 'package:acter/common/actions/redact_content.dart'; -import 'package:acter/common/actions/report_content.dart'; -import 'package:acter/common/providers/common_providers.dart'; -import 'package:acter/common/providers/room_providers.dart'; -import 'package:acter/common/widgets/edit_html_description_sheet.dart'; -import 'package:acter/common/widgets/edit_link_sheet.dart'; -import 'package:acter/common/widgets/edit_title_sheet.dart'; -import 'package:acter/features/attachments/widgets/attachment_section.dart'; -import 'package:acter/features/comments/widgets/comments_section.dart'; -import 'package:acter/features/pins/Utils/pins_utils.dart'; -import 'package:acter/features/pins/providers/pins_provider.dart'; -import 'package:acter/features/pins/widgets/pin_item.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'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:logging/logging.dart'; -import 'package:skeletonizer/skeletonizer.dart'; - -final _log = Logger('a3::pins::pin_page'); - -class PinPage extends ConsumerWidget { - static const pinPageKey = Key('pin-page'); - static const actionMenuKey = Key('pin-action-menu'); - static const editBtnKey = Key('pin-edit-btn'); - static const titleFieldKey = Key('edit-pin-title-field'); - - final String pinId; - - // ignore: use_key_in_widget_constructors - const PinPage({ - Key key = pinPageKey, - required this.pinId, - }); - - // pin actions menu builder - Widget _buildActionMenu( - BuildContext context, - WidgetRef ref, - ActerPin pin, - ) { - final spaceId = pin.roomIdStr(); - List> actions = []; - final pinEditNotifier = ref.watch(pinEditProvider(pin).notifier); - final canRedact = ref.watch(canRedactProvider(pin)); - final membership = ref.watch(roomMembershipProvider(spaceId)).valueOrNull; - if (membership != null) { - if (membership.canString('CanPostPin')) { - actions.add( - PopupMenuItem( - key: PinPage.editBtnKey, - onTap: () { - showEditTitleBottomSheet( - context: context, - bottomSheetTitle: L10n.of(context).editName, - titleValue: pin.title(), - onSave: (newTitle) async { - pinEditNotifier.setTitle(newTitle); - savePinTitle(context, pin, newTitle); - }, - ); - }, - child: Text(L10n.of(context).editTitle), - ), - ); - - actions.add( - PopupMenuItem( - key: PinPage.editBtnKey, - onTap: () { - showEditLinkBottomSheet( - context: context, - bottomSheetTitle: L10n.of(context).editLink, - linkValue: pin.url() ?? '', - onSave: (newLink) async { - pinEditNotifier.setLink(newLink); - savePinLink(context, pin, newLink); - }, - ); - }, - child: Text(L10n.of(context).editLink), - ), - ); - - actions.add( - PopupMenuItem( - key: PinPage.editBtnKey, - onTap: () { - showEditHtmlDescriptionBottomSheet( - context: context, - descriptionHtmlValue: pin.content()?.formattedBody(), - descriptionMarkdownValue: pin.content()?.body(), - onSave: (htmlBodyDescription, plainDescription) async { - saveDescription( - context, - htmlBodyDescription, - plainDescription, - pin, - ); - }, - ); - }, - child: Text(L10n.of(context).editDescription), - ), - ); - } - - if (canRedact.valueOrNull == true) { - final roomId = pin.roomIdStr(); - actions.add( - PopupMenuItem( - onTap: () => showRedactDialog( - context: context, - pin: pin, - roomId: roomId, - ), - child: Text( - L10n.of(context).removePin, - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - ), - ); - } else { - actions.add( - PopupMenuItem( - onTap: () => showReportDialog(context, pin), - child: Row( - children: [ - Icon( - Atlas.warning_thin, - color: Theme.of(context).colorScheme.error, - ), - const SizedBox(width: 10), - Text(L10n.of(context).reportPin), - ], - ), - ), - ); - } - } - - return PopupMenuButton( - key: PinPage.actionMenuKey, - icon: const Icon(Atlas.dots_vertical_thin), - itemBuilder: (context) => actions, - ); - } - - // redact pin dialog - void showRedactDialog({ - required BuildContext context, - required ActerPin pin, - required String roomId, - }) { - openRedactContentDialog( - context, - title: L10n.of(context).removeThisPin, - eventId: pin.eventIdStr(), - onSuccess: () { - Navigator.pop(context); - }, - roomId: roomId, - isSpace: true, - ); - } - - // report pin dialog - void showReportDialog(BuildContext context, ActerPin pin) { - openReportContentDialog( - context, - title: L10n.of(context).reportThisPin, - description: L10n.of(context).reportThisContent, - eventId: pinId, - roomId: pin.roomIdStr(), - senderId: pin.sender().toString(), - isSpace: true, - ); - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - final pin = ref.watch(pinProvider(pinId)); - - return Scaffold( - body: CustomScrollView( - slivers: [ - pin.when( - data: (acterPin) { - return SliverAppBar( - centerTitle: false, - leadingWidth: 40, - toolbarHeight: 100, - title: _buildTitle(context, ref, acterPin), - actions: [ - _buildActionMenu(context, ref, acterPin), - ], - ); - }, - loading: () => SliverAppBar( - title: Skeletonizer( - child: Text(L10n.of(context).loadingPin), - ), - ), - error: (err, st) { - _log.severe('Failed to load pin', err, st); - return SliverAppBar( - title: Text(L10n.of(context).errorLoadingPin(err)), - ); - }, - ), - SliverToBoxAdapter( - child: pin.when( - data: (acterPin) => Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - PinItem(acterPin), - const SizedBox(height: 20), - AttachmentSectionWidget(manager: acterPin.attachments()), - const SizedBox(height: 20), - CommentsSection(manager: acterPin.comments()), - ], - ), - error: (err, st) { - _log.severe('Failed to load pin', err, st); - return Text(L10n.of(context).errorLoadingPin(err)); - }, - loading: () => const Skeletonizer( - child: Card(), - ), - ), - ), - ], - ), - ); - } - - // pin title builder - Widget _buildTitle(BuildContext context, WidgetRef ref, ActerPin pin) { - final pinEdit = ref.watch(pinEditProvider(pin)); - final pinEditNotifier = ref.watch(pinEditProvider(pin).notifier); - return Visibility( - visible: !pinEdit.editMode, - replacement: TextFormField( - key: PinPage.titleFieldKey, - initialValue: pin.title(), - style: Theme.of(context).textTheme.titleLarge, - onChanged: (val) => pinEditNotifier.setTitle(val), - ), - child: SelectionArea( - child: GestureDetector( - onTap: () { - final membership = - ref.watch(roomMembershipProvider(pin.roomIdStr())).valueOrNull; - if (membership != null) { - if (membership.canString('CanPostPin')) { - showEditTitleBottomSheet( - context: context, - bottomSheetTitle: L10n.of(context).editName, - titleValue: pin.title(), - onSave: (newTitle) async { - pinEditNotifier.setTitle(newTitle); - savePinTitle(context, pin, newTitle); - }, - ); - } - } - }, - child: Text( - pin.title(), - overflow: TextOverflow.ellipsis, - style: Theme.of(context).textTheme.titleLarge, - ), - ), - ), - ); - } -} diff --git a/app/lib/features/pins/pages/pins_list_page.dart b/app/lib/features/pins/pages/pins_list_page.dart index dcdd28620449..e9d971a92884 100644 --- a/app/lib/features/pins/pages/pins_list_page.dart +++ b/app/lib/features/pins/pages/pins_list_page.dart @@ -52,7 +52,7 @@ class _AllPinsPageConsumerState extends ConsumerState { Text(L10n.of(context).pins), if (widget.spaceId != null) SpaceNameWidget( - spaceId: widget.spaceId, + spaceId: widget.spaceId!, ), ], ), diff --git a/app/lib/features/tasks/pages/tasks_list_page.dart b/app/lib/features/tasks/pages/tasks_list_page.dart index 095e5fab8ff6..c5157317ac51 100644 --- a/app/lib/features/tasks/pages/tasks_list_page.dart +++ b/app/lib/features/tasks/pages/tasks_list_page.dart @@ -54,7 +54,7 @@ class _TasksListPageConsumerState extends ConsumerState { Text(L10n.of(context).tasks), if (widget.spaceId != null) SpaceNameWidget( - spaceId: widget.spaceId, + spaceId: widget.spaceId!, ), ], ), diff --git a/app/lib/l10n/app_en.arb b/app/lib/l10n/app_en.arb index 47b733f8ecc4..f6ac1898eacc 100644 --- a/app/lib/l10n/app_en.arb +++ b/app/lib/l10n/app_en.arb @@ -2104,5 +2104,6 @@ "attachmentEmptyStateTitle": "No attachments found.", "text": "text", "audio": "Audio", - "pinDetails": "Pin Details" + "pinDetails": "Pin Details", + "inKey": "In" }