From ece29b95f5db1d17ac94149fe9d930634c610cc1 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 21 Sep 2022 11:37:42 +0800 Subject: [PATCH 1/2] refactor: separate the trash page widget from trash.dart file --- .../app_flowy/lib/plugins/trash/trash.dart | 157 +----------------- 1 file changed, 1 insertion(+), 156 deletions(-) diff --git a/frontend/app_flowy/lib/plugins/trash/trash.dart b/frontend/app_flowy/lib/plugins/trash/trash.dart index f338040b28..eba60b2e38 100644 --- a/frontend/app_flowy/lib/plugins/trash/trash.dart +++ b/frontend/app_flowy/lib/plugins/trash/trash.dart @@ -3,26 +3,13 @@ export "./src/trash_cell.dart"; export "./src/trash_header.dart"; import 'package:app_flowy/startup/plugin/plugin.dart'; -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/plugins/trash/application/trash_bloc.dart'; import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/image.dart'; -import 'package:flowy_infra/theme.dart'; -import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; -import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; -import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; -import 'package:flowy_infra_ui/style_widget/button.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:styled_widget/styled_widget.dart'; import 'package:app_flowy/generated/locale_keys.g.dart'; -import 'src/sizes.dart'; -import 'src/trash_cell.dart'; -import 'src/trash_header.dart'; +import 'trash_page.dart'; class TrashPluginBuilder extends PluginBuilder { @override @@ -71,145 +58,3 @@ class TrashPluginDisplay extends PluginDisplay { @override List get navigationItems => [this]; } - -class TrashPage extends StatefulWidget { - const TrashPage({Key? key}) : super(key: key); - - @override - State createState() => _TrashPageState(); -} - -class _TrashPageState extends State { - final ScrollController _scrollController = ScrollController(); - @override - Widget build(BuildContext context) { - final theme = context.watch(); - const horizontalPadding = 80.0; - return BlocProvider( - create: (context) => getIt()..add(const TrashEvent.initial()), - child: BlocBuilder( - builder: (context, state) { - return SizedBox.expand( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - _renderTopBar(context, theme, state), - const VSpace(32), - _renderTrashList(context, state), - ], - ).padding(horizontal: horizontalPadding, vertical: 48), - ); - }, - ), - ); - } - - Widget _renderTrashList(BuildContext context, TrashState state) { - const barSize = 6.0; - return Expanded( - child: ScrollbarListStack( - axis: Axis.vertical, - controller: _scrollController, - scrollbarPadding: EdgeInsets.only(top: TrashSizes.headerHeight), - barSize: barSize, - child: StyledSingleChildScrollView( - controller: ScrollController(), - barSize: barSize, - axis: Axis.horizontal, - child: SizedBox( - width: TrashSizes.totalWidth, - child: ScrollConfiguration( - behavior: const ScrollBehavior().copyWith(scrollbars: false), - child: CustomScrollView( - shrinkWrap: true, - physics: StyledScrollPhysics(), - controller: _scrollController, - slivers: [ - _renderListHeader(context, state), - _renderListBody(context, state), - ], - ), - ), - ), - ), - ), - ); - } - - Widget _renderTopBar(BuildContext context, AppTheme theme, TrashState state) { - return SizedBox( - height: 36, - child: Row( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - FlowyText.semibold(LocaleKeys.trash_text.tr()), - const Spacer(), - IntrinsicWidth( - child: FlowyButton( - text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), - fontSize: 12), - leftIcon: svgWidget('editor/restore', color: theme.iconColor), - hoverColor: theme.hover, - onTap: () => context.read().add( - const TrashEvent.restoreAll(), - ), - ), - ), - const HSpace(6), - IntrinsicWidth( - child: FlowyButton( - text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), - fontSize: 12), - leftIcon: svgWidget('editor/delete', color: theme.iconColor), - hoverColor: theme.hover, - onTap: () => - context.read().add(const TrashEvent.deleteAll()), - ), - ) - ], - ), - ); - } - - Widget _renderListHeader(BuildContext context, TrashState state) { - return SliverPersistentHeader( - delegate: TrashHeaderDelegate(), - floating: true, - pinned: true, - ); - } - - Widget _renderListBody(BuildContext context, TrashState state) { - return SliverList( - delegate: SliverChildBuilderDelegate( - (BuildContext context, int index) { - final object = state.objects[index]; - return SizedBox( - height: 42, - child: TrashCell( - object: object, - onRestore: () { - context.read().add(TrashEvent.putback(object.id)); - }, - onDelete: () => - context.read().add(TrashEvent.delete(object)), - ), - ); - }, - childCount: state.objects.length, - addAutomaticKeepAlives: false, - ), - ); - } -} -// class TrashScrollbar extends ScrollBehavior { -// @override -// Widget buildScrollbar(BuildContext context, Widget child, ScrollableDetails details) { -// return ScrollbarListStack( -// controller: details.controller, -// axis: Axis.vertical, -// barSize: 6, -// child: child, -// ); -// } -// } From 7e972c3ccd16b206a508c7cd0ccc10c83bee7823 Mon Sep 17 00:00:00 2001 From: appflowy Date: Wed, 21 Sep 2022 11:46:32 +0800 Subject: [PATCH 2/2] chore: display highlight color in delete/restore button --- .../lib/plugins/trash/src/trash_cell.dart | 30 +++- .../lib/plugins/trash/trash_page.dart | 150 ++++++++++++++++++ 2 files changed, 173 insertions(+), 7 deletions(-) create mode 100644 frontend/app_flowy/lib/plugins/trash/trash_page.dart diff --git a/frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart b/frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart index 4d6604e4af..97f56ba89a 100644 --- a/frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart +++ b/frontend/app_flowy/lib/plugins/trash/src/trash_cell.dart @@ -15,26 +15,41 @@ class TrashCell extends StatelessWidget { final VoidCallback onRestore; final VoidCallback onDelete; final TrashPB object; - const TrashCell({required this.object, required this.onRestore, required this.onDelete, Key? key}) : super(key: key); + const TrashCell( + {required this.object, + required this.onRestore, + required this.onDelete, + Key? key}) + : super(key: key); @override Widget build(BuildContext context) { final theme = context.watch(); return Row( children: [ - SizedBox(width: TrashSizes.fileNameWidth, child: FlowyText(object.name, fontSize: 12)), - SizedBox(width: TrashSizes.lashModifyWidth, child: FlowyText(dateFormatter(object.modifiedTime), fontSize: 12)), - SizedBox(width: TrashSizes.createTimeWidth, child: FlowyText(dateFormatter(object.createTime), fontSize: 12)), + SizedBox( + width: TrashSizes.fileNameWidth, + child: FlowyText(object.name, fontSize: 12)), + SizedBox( + width: TrashSizes.lashModifyWidth, + child: FlowyText(dateFormatter(object.modifiedTime), fontSize: 12)), + SizedBox( + width: TrashSizes.createTimeWidth, + child: FlowyText(dateFormatter(object.createTime), fontSize: 12)), const Spacer(), FlowyIconButton( - width: 16, + width: 26, onPressed: onRestore, + hoverColor: theme.hover, + iconPadding: const EdgeInsets.all(5), icon: svgWidget("editor/restore", color: theme.iconColor), ), const HSpace(20), FlowyIconButton( - width: 16, + width: 26, onPressed: onDelete, + hoverColor: theme.hover, + iconPadding: const EdgeInsets.all(5), icon: svgWidget("editor/delete", color: theme.iconColor), ), ], @@ -43,7 +58,8 @@ class TrashCell extends StatelessWidget { String dateFormatter($fixnum.Int64 inputTimestamps) { var outputFormat = DateFormat('MM/dd/yyyy hh:mm a'); - var date = DateTime.fromMillisecondsSinceEpoch(inputTimestamps.toInt() * 1000); + var date = + DateTime.fromMillisecondsSinceEpoch(inputTimestamps.toInt() * 1000); var outputDate = outputFormat.format(date); return outputDate; } diff --git a/frontend/app_flowy/lib/plugins/trash/trash_page.dart b/frontend/app_flowy/lib/plugins/trash/trash_page.dart new file mode 100644 index 0000000000..2c0ed36633 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/trash/trash_page.dart @@ -0,0 +1,150 @@ +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/plugins/trash/src/sizes.dart'; +import 'package:app_flowy/plugins/trash/src/trash_header.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flowy_infra/theme.dart'; +import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_scrollview.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:styled_widget/styled_widget.dart'; + +import 'application/trash_bloc.dart'; +import 'src/trash_cell.dart'; + +class TrashPage extends StatefulWidget { + const TrashPage({Key? key}) : super(key: key); + + @override + State createState() => _TrashPageState(); +} + +class _TrashPageState extends State { + final ScrollController _scrollController = ScrollController(); + @override + Widget build(BuildContext context) { + final theme = context.watch(); + const horizontalPadding = 80.0; + return BlocProvider( + create: (context) => getIt()..add(const TrashEvent.initial()), + child: BlocBuilder( + builder: (context, state) { + return SizedBox.expand( + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + _renderTopBar(context, theme, state), + const VSpace(32), + _renderTrashList(context, state), + ], + ).padding(horizontal: horizontalPadding, vertical: 48), + ); + }, + ), + ); + } + + Widget _renderTrashList(BuildContext context, TrashState state) { + const barSize = 6.0; + return Expanded( + child: ScrollbarListStack( + axis: Axis.vertical, + controller: _scrollController, + scrollbarPadding: EdgeInsets.only(top: TrashSizes.headerHeight), + barSize: barSize, + child: StyledSingleChildScrollView( + controller: ScrollController(), + barSize: barSize, + axis: Axis.horizontal, + child: SizedBox( + width: TrashSizes.totalWidth, + child: ScrollConfiguration( + behavior: const ScrollBehavior().copyWith(scrollbars: false), + child: CustomScrollView( + shrinkWrap: true, + physics: StyledScrollPhysics(), + controller: _scrollController, + slivers: [ + _renderListHeader(context, state), + _renderListBody(context, state), + ], + ), + ), + ), + ), + ), + ); + } + + Widget _renderTopBar(BuildContext context, AppTheme theme, TrashState state) { + return SizedBox( + height: 36, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + FlowyText.semibold(LocaleKeys.trash_text.tr()), + const Spacer(), + IntrinsicWidth( + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), + fontSize: 12), + leftIcon: svgWidget('editor/restore', color: theme.iconColor), + hoverColor: theme.hover, + onTap: () => context.read().add( + const TrashEvent.restoreAll(), + ), + ), + ), + const HSpace(6), + IntrinsicWidth( + child: FlowyButton( + text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), + fontSize: 12), + leftIcon: svgWidget('editor/delete', color: theme.iconColor), + hoverColor: theme.hover, + onTap: () => + context.read().add(const TrashEvent.deleteAll()), + ), + ) + ], + ), + ); + } + + Widget _renderListHeader(BuildContext context, TrashState state) { + return SliverPersistentHeader( + delegate: TrashHeaderDelegate(), + floating: true, + pinned: true, + ); + } + + Widget _renderListBody(BuildContext context, TrashState state) { + return SliverList( + delegate: SliverChildBuilderDelegate( + (BuildContext context, int index) { + final object = state.objects[index]; + return SizedBox( + height: 42, + child: TrashCell( + object: object, + onRestore: () { + context.read().add(TrashEvent.putback(object.id)); + }, + onDelete: () => + context.read().add(TrashEvent.delete(object)), + ), + ); + }, + childCount: state.objects.length, + addAutomaticKeepAlives: false, + ), + ); + } +}