From a668e0bd09515262ef21b543dc7dc0bbc0431fb9 Mon Sep 17 00:00:00 2001 From: "Lucas.Xu" Date: Mon, 17 Jun 2024 18:01:05 +0800 Subject: [PATCH] feat: add a pinned icon after page name --- .../menu/sidebar/favorites/favorite_menu.dart | 102 +++++++++++------- .../home/menu/view/view_item.dart | 32 ++++-- .../flowy_icons/16x/favorite_pin.svg | 3 + 3 files changed, 95 insertions(+), 42 deletions(-) create mode 100644 frontend/resources/flowy_icons/16x/favorite_pin.svg diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart index e2fcc2021c..71c36a0619 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/favorites/favorite_menu.dart @@ -2,6 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/sidebar/folder/folder_bloc.dart'; import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; +import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_menu_bloc.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_more_actions.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/favorites/favorite_pin_action.dart'; @@ -36,9 +37,6 @@ class FavoriteMenu extends StatelessWidget { FavoriteMenuBloc()..add(const FavoriteMenuEvent.initial()), child: BlocBuilder( builder: (context, state) { - if (state.views.isEmpty) { - return const SizedBox.shrink(); - } return Column( mainAxisSize: MainAxisSize.min, children: [ @@ -52,7 +50,10 @@ class FavoriteMenu extends StatelessWidget { }, ), const VSpace(12), - _buildViews(context, state), + _FavoriteGroups( + minWidth: minWidth, + state: state, + ), ], ); }, @@ -60,8 +61,67 @@ class FavoriteMenu extends StatelessWidget { ), ); } +} - Widget _buildViews(BuildContext context, FavoriteMenuState state) { +class _FavoriteGroupedViews extends StatelessWidget { + const _FavoriteGroupedViews({ + required this.views, + }); + + final List views; + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + children: views + .map( + (e) => ViewItem( + key: ValueKey(e.id), + view: e, + spaceType: FolderSpaceType.favorite, + level: 0, + onSelected: (_, view) { + context.read().openPlugin(view); + PopoverContainer.maybeOf(context)?.close(); + }, + isFeedback: false, + isDraggable: false, + shouldRenderChildren: false, + extendBuilder: (view) => view.isPinned + ? [ + const HSpace(4.0), + const FlowySvg( + FlowySvgs.favorite_pin_s, + blendMode: null, + ), + ] + : [], + leftIconBuilder: (_, __) => const HSpace(4.0), + rightIconsBuilder: (_, view) => [ + FavoriteMoreActions(view: view), + const HSpace(6.0), + FavoritePinAction(view: view), + const HSpace(4.0), + ], + ), + ) + .toList(), + ); + } +} + +class _FavoriteGroups extends StatelessWidget { + const _FavoriteGroups({ + required this.minWidth, + required this.state, + }); + + final double minWidth; + final FavoriteMenuState state; + + @override + Widget build(BuildContext context) { final today = _buildGroups( context, state.todayViews, @@ -131,41 +191,11 @@ class FavoriteMenu extends StatelessWidget { ), ), const VSpace(2), - _buildGroupedViews(context, views), + _FavoriteGroupedViews(views: views), const VSpace(8), ], ]; } - - Widget _buildGroupedViews(BuildContext context, List views) { - return Column( - mainAxisSize: MainAxisSize.min, - children: views - .map( - (e) => ViewItem( - key: ValueKey(e.id), - view: e, - spaceType: FolderSpaceType.favorite, - level: 0, - onSelected: (_, view) { - context.read().openPlugin(view); - PopoverContainer.maybeOf(context)?.close(); - }, - isFeedback: false, - isDraggable: false, - shouldRenderChildren: false, - leftIconBuilder: (_, __) => const HSpace(4.0), - rightIconsBuilder: (_, view) => [ - FavoriteMoreActions(view: view), - const HSpace(6.0), - FavoritePinAction(view: view), - const HSpace(4.0), - ], - ), - ) - .toList(), - ); - } } class _FavoriteSearchField extends StatefulWidget { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart index b94f306422..290f5ba4e0 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/view/view_item.dart @@ -60,6 +60,7 @@ class ViewItem extends StatelessWidget { this.rightIconsBuilder, this.shouldLoadChildViews = true, this.isExpandedNotifier, + this.extendBuilder, }); final ViewPB view; @@ -113,6 +114,8 @@ class ViewItem extends StatelessWidget { final bool shouldLoadChildViews; final PropertyValueNotifier? isExpandedNotifier; + final List Function(ViewPB view)? extendBuilder; + @override Widget build(BuildContext context) { return BlocProvider( @@ -148,6 +151,7 @@ class ViewItem extends StatelessWidget { leftIconBuilder: leftIconBuilder, rightIconsBuilder: rightIconsBuilder, isExpandedNotifier: isExpandedNotifier, + extendBuilder: extendBuilder, ); }, ), @@ -181,6 +185,7 @@ class InnerViewItem extends StatefulWidget { required this.leftIconBuilder, required this.rightIconsBuilder, this.isExpandedNotifier, + required this.extendBuilder, }); final ViewPB view; @@ -210,6 +215,7 @@ class InnerViewItem extends StatefulWidget { final ViewItemRightIconsBuilder? rightIconsBuilder; final PropertyValueNotifier? isExpandedNotifier; + final List Function(ViewPB view)? extendBuilder; @override State createState() => _InnerViewItemState(); @@ -247,6 +253,7 @@ class _InnerViewItemState extends State { isHovered: widget.isHovered, leftIconBuilder: widget.leftIconBuilder, rightIconsBuilder: widget.rightIconsBuilder, + extendBuilder: widget.extendBuilder, ); // if the view is expanded and has child views, render its child views @@ -270,6 +277,7 @@ class _InnerViewItemState extends State { isHovered: widget.isHovered, leftIconBuilder: widget.leftIconBuilder, rightIconsBuilder: widget.rightIconsBuilder, + extendBuilder: widget.extendBuilder, ); }).toList(); @@ -315,6 +323,7 @@ class _InnerViewItemState extends State { isFeedback: true, leftIconBuilder: widget.leftIconBuilder, rightIconsBuilder: widget.rightIconsBuilder, + extendBuilder: widget.extendBuilder, ), ); }, @@ -389,6 +398,7 @@ class SingleInnerViewItem extends StatefulWidget { this.isHovered, required this.leftIconBuilder, required this.rightIconsBuilder, + required this.extendBuilder, }); final ViewPB view; @@ -413,6 +423,8 @@ class SingleInnerViewItem extends StatefulWidget { final ViewItemLeftIconBuilder? leftIconBuilder; final ViewItemRightIconsBuilder? rightIconsBuilder; + final List Function(ViewPB view)? extendBuilder; + @override State createState() => _SingleInnerViewItemState(); } @@ -453,6 +465,10 @@ class _SingleInnerViewItemState extends State { } Widget _buildViewItem(bool onHover, [bool isSelected = false]) { + final name = FlowyText.regular( + widget.view.name, + overflow: TextOverflow.ellipsis, + ); final children = [ const HSpace(2), // expand icon or placeholder @@ -462,12 +478,16 @@ class _SingleInnerViewItemState extends State { _buildViewIconButton(), const HSpace(6), // title - Expanded( - child: FlowyText.regular( - widget.view.name, - overflow: TextOverflow.ellipsis, - ), - ), + widget.extendBuilder != null + ? Expanded( + child: Row( + children: [ + name, + ...widget.extendBuilder!(widget.view), + ], + ), + ) + : Expanded(child: name), ]; // hover action diff --git a/frontend/resources/flowy_icons/16x/favorite_pin.svg b/frontend/resources/flowy_icons/16x/favorite_pin.svg new file mode 100644 index 0000000000..fa4065cd0a --- /dev/null +++ b/frontend/resources/flowy_icons/16x/favorite_pin.svg @@ -0,0 +1,3 @@ + + +