diff --git a/app_flowy/lib/workspace/application/trash/trash_bloc.dart b/app_flowy/lib/workspace/application/trash/trash_bloc.dart index 0059b3ff4d..1991f6e225 100644 --- a/app_flowy/lib/workspace/application/trash/trash_bloc.dart +++ b/app_flowy/lib/workspace/application/trash/trash_bloc.dart @@ -26,6 +26,16 @@ class TrashBloc extends Bloc { didReceiveTrash: (e) async* { yield state.copyWith(objects: e.trash); }, + putback: (e) async* { + final result = await iTrash.putback(e.trashId); + result.fold((l) {}, (error) {}); + }, + delete: (e) async* { + final result = await iTrash.delete(e.trashId); + result.fold((l) {}, (error) {}); + }, + deleteAll: (e) async* {}, + restoreAll: (e) async* {}, ); } @@ -51,6 +61,10 @@ class TrashBloc extends Bloc { class TrashEvent with _$TrashEvent { const factory TrashEvent.initial() = Initial; const factory TrashEvent.didReceiveTrash(List trash) = ReceiveTrash; + const factory TrashEvent.putback(String trashId) = Putback; + const factory TrashEvent.delete(String trashId) = Delete; + const factory TrashEvent.restoreAll() = RestoreAll; + const factory TrashEvent.deleteAll() = DeleteAll; } @freezed diff --git a/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart b/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart index eaac4ebd12..3913eaff6b 100644 --- a/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart +++ b/app_flowy/lib/workspace/application/trash/trash_bloc.freezed.dart @@ -25,6 +25,26 @@ class _$TrashEventTearOff { trash, ); } + + Putback putback(String trashId) { + return Putback( + trashId, + ); + } + + Delete delete(String trashId) { + return Delete( + trashId, + ); + } + + RestoreAll restoreAll() { + return const RestoreAll(); + } + + DeleteAll deleteAll() { + return const DeleteAll(); + } } /// @nodoc @@ -36,12 +56,20 @@ mixin _$TrashEvent { TResult when({ required TResult Function() initial, required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeWhen({ TResult Function()? initial, TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -49,12 +77,20 @@ mixin _$TrashEvent { TResult map({ required TResult Function(Initial value) initial, required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, }) => throw _privateConstructorUsedError; @optionalTypeArgs TResult maybeMap({ TResult Function(Initial value)? initial, TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, required TResult orElse(), }) => throw _privateConstructorUsedError; @@ -115,6 +151,10 @@ class _$Initial implements Initial { TResult when({ required TResult Function() initial, required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, }) { return initial(); } @@ -124,6 +164,10 @@ class _$Initial implements Initial { TResult maybeWhen({ TResult Function()? initial, TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, required TResult orElse(), }) { if (initial != null) { @@ -137,6 +181,10 @@ class _$Initial implements Initial { TResult map({ required TResult Function(Initial value) initial, required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, }) { return initial(this); } @@ -146,6 +194,10 @@ class _$Initial implements Initial { TResult maybeMap({ TResult Function(Initial value)? initial, TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, required TResult orElse(), }) { if (initial != null) { @@ -225,6 +277,10 @@ class _$ReceiveTrash implements ReceiveTrash { TResult when({ required TResult Function() initial, required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, }) { return didReceiveTrash(trash); } @@ -234,6 +290,10 @@ class _$ReceiveTrash implements ReceiveTrash { TResult maybeWhen({ TResult Function()? initial, TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, required TResult orElse(), }) { if (didReceiveTrash != null) { @@ -247,6 +307,10 @@ class _$ReceiveTrash implements ReceiveTrash { TResult map({ required TResult Function(Initial value) initial, required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, }) { return didReceiveTrash(this); } @@ -256,6 +320,10 @@ class _$ReceiveTrash implements ReceiveTrash { TResult maybeMap({ TResult Function(Initial value)? initial, TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, required TResult orElse(), }) { if (didReceiveTrash != null) { @@ -274,6 +342,461 @@ abstract class ReceiveTrash implements TrashEvent { throw _privateConstructorUsedError; } +/// @nodoc +abstract class $PutbackCopyWith<$Res> { + factory $PutbackCopyWith(Putback value, $Res Function(Putback) then) = + _$PutbackCopyWithImpl<$Res>; + $Res call({String trashId}); +} + +/// @nodoc +class _$PutbackCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res> + implements $PutbackCopyWith<$Res> { + _$PutbackCopyWithImpl(Putback _value, $Res Function(Putback) _then) + : super(_value, (v) => _then(v as Putback)); + + @override + Putback get _value => super._value as Putback; + + @override + $Res call({ + Object? trashId = freezed, + }) { + return _then(Putback( + trashId == freezed + ? _value.trashId + : trashId // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$Putback implements Putback { + const _$Putback(this.trashId); + + @override + final String trashId; + + @override + String toString() { + return 'TrashEvent.putback(trashId: $trashId)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is Putback && + (identical(other.trashId, trashId) || + const DeepCollectionEquality().equals(other.trashId, trashId))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ const DeepCollectionEquality().hash(trashId); + + @JsonKey(ignore: true) + @override + $PutbackCopyWith get copyWith => + _$PutbackCopyWithImpl(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, + }) { + return putback(trashId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, + required TResult orElse(), + }) { + if (putback != null) { + return putback(trashId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, + }) { + return putback(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, + required TResult orElse(), + }) { + if (putback != null) { + return putback(this); + } + return orElse(); + } +} + +abstract class Putback implements TrashEvent { + const factory Putback(String trashId) = _$Putback; + + String get trashId => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $PutbackCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $DeleteCopyWith<$Res> { + factory $DeleteCopyWith(Delete value, $Res Function(Delete) then) = + _$DeleteCopyWithImpl<$Res>; + $Res call({String trashId}); +} + +/// @nodoc +class _$DeleteCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res> + implements $DeleteCopyWith<$Res> { + _$DeleteCopyWithImpl(Delete _value, $Res Function(Delete) _then) + : super(_value, (v) => _then(v as Delete)); + + @override + Delete get _value => super._value as Delete; + + @override + $Res call({ + Object? trashId = freezed, + }) { + return _then(Delete( + trashId == freezed + ? _value.trashId + : trashId // ignore: cast_nullable_to_non_nullable + as String, + )); + } +} + +/// @nodoc + +class _$Delete implements Delete { + const _$Delete(this.trashId); + + @override + final String trashId; + + @override + String toString() { + return 'TrashEvent.delete(trashId: $trashId)'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || + (other is Delete && + (identical(other.trashId, trashId) || + const DeepCollectionEquality().equals(other.trashId, trashId))); + } + + @override + int get hashCode => + runtimeType.hashCode ^ const DeepCollectionEquality().hash(trashId); + + @JsonKey(ignore: true) + @override + $DeleteCopyWith get copyWith => + _$DeleteCopyWithImpl(this, _$identity); + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, + }) { + return delete(trashId); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, + required TResult orElse(), + }) { + if (delete != null) { + return delete(trashId); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, + }) { + return delete(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, + required TResult orElse(), + }) { + if (delete != null) { + return delete(this); + } + return orElse(); + } +} + +abstract class Delete implements TrashEvent { + const factory Delete(String trashId) = _$Delete; + + String get trashId => throw _privateConstructorUsedError; + @JsonKey(ignore: true) + $DeleteCopyWith get copyWith => throw _privateConstructorUsedError; +} + +/// @nodoc +abstract class $RestoreAllCopyWith<$Res> { + factory $RestoreAllCopyWith( + RestoreAll value, $Res Function(RestoreAll) then) = + _$RestoreAllCopyWithImpl<$Res>; +} + +/// @nodoc +class _$RestoreAllCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res> + implements $RestoreAllCopyWith<$Res> { + _$RestoreAllCopyWithImpl(RestoreAll _value, $Res Function(RestoreAll) _then) + : super(_value, (v) => _then(v as RestoreAll)); + + @override + RestoreAll get _value => super._value as RestoreAll; +} + +/// @nodoc + +class _$RestoreAll implements RestoreAll { + const _$RestoreAll(); + + @override + String toString() { + return 'TrashEvent.restoreAll()'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || (other is RestoreAll); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, + }) { + return restoreAll(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, + required TResult orElse(), + }) { + if (restoreAll != null) { + return restoreAll(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, + }) { + return restoreAll(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, + required TResult orElse(), + }) { + if (restoreAll != null) { + return restoreAll(this); + } + return orElse(); + } +} + +abstract class RestoreAll implements TrashEvent { + const factory RestoreAll() = _$RestoreAll; +} + +/// @nodoc +abstract class $DeleteAllCopyWith<$Res> { + factory $DeleteAllCopyWith(DeleteAll value, $Res Function(DeleteAll) then) = + _$DeleteAllCopyWithImpl<$Res>; +} + +/// @nodoc +class _$DeleteAllCopyWithImpl<$Res> extends _$TrashEventCopyWithImpl<$Res> + implements $DeleteAllCopyWith<$Res> { + _$DeleteAllCopyWithImpl(DeleteAll _value, $Res Function(DeleteAll) _then) + : super(_value, (v) => _then(v as DeleteAll)); + + @override + DeleteAll get _value => super._value as DeleteAll; +} + +/// @nodoc + +class _$DeleteAll implements DeleteAll { + const _$DeleteAll(); + + @override + String toString() { + return 'TrashEvent.deleteAll()'; + } + + @override + bool operator ==(dynamic other) { + return identical(this, other) || (other is DeleteAll); + } + + @override + int get hashCode => runtimeType.hashCode; + + @override + @optionalTypeArgs + TResult when({ + required TResult Function() initial, + required TResult Function(List trash) didReceiveTrash, + required TResult Function(String trashId) putback, + required TResult Function(String trashId) delete, + required TResult Function() restoreAll, + required TResult Function() deleteAll, + }) { + return deleteAll(); + } + + @override + @optionalTypeArgs + TResult maybeWhen({ + TResult Function()? initial, + TResult Function(List trash)? didReceiveTrash, + TResult Function(String trashId)? putback, + TResult Function(String trashId)? delete, + TResult Function()? restoreAll, + TResult Function()? deleteAll, + required TResult orElse(), + }) { + if (deleteAll != null) { + return deleteAll(); + } + return orElse(); + } + + @override + @optionalTypeArgs + TResult map({ + required TResult Function(Initial value) initial, + required TResult Function(ReceiveTrash value) didReceiveTrash, + required TResult Function(Putback value) putback, + required TResult Function(Delete value) delete, + required TResult Function(RestoreAll value) restoreAll, + required TResult Function(DeleteAll value) deleteAll, + }) { + return deleteAll(this); + } + + @override + @optionalTypeArgs + TResult maybeMap({ + TResult Function(Initial value)? initial, + TResult Function(ReceiveTrash value)? didReceiveTrash, + TResult Function(Putback value)? putback, + TResult Function(Delete value)? delete, + TResult Function(RestoreAll value)? restoreAll, + TResult Function(DeleteAll value)? deleteAll, + required TResult orElse(), + }) { + if (deleteAll != null) { + return deleteAll(this); + } + return orElse(); + } +} + +abstract class DeleteAll implements TrashEvent { + const factory DeleteAll() = _$DeleteAll; +} + /// @nodoc class _$TrashStateTearOff { const _$TrashStateTearOff(); diff --git a/app_flowy/lib/workspace/domain/i_trash.dart b/app_flowy/lib/workspace/domain/i_trash.dart index f57514ae68..69963bccd1 100644 --- a/app_flowy/lib/workspace/domain/i_trash.dart +++ b/app_flowy/lib/workspace/domain/i_trash.dart @@ -5,6 +5,10 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/trash_create.pb.dart'; abstract class ITrash { Future, WorkspaceError>> readTrash(); + + Future> putback(String trashId); + + Future> delete(String trashId); } typedef TrashUpdatedCallback = void Function(Either, WorkspaceError> trashOrFailed); diff --git a/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart b/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart index 251dbcc1d8..ac5aa6fe1b 100644 --- a/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart +++ b/app_flowy/lib/workspace/infrastructure/i_trash_impl.dart @@ -18,6 +18,16 @@ class ITrashImpl implements ITrash { ); }); } + + @override + Future> putback(String trashId) { + return repo.putback(trashId); + } + + @override + Future> delete(String trashId) { + return repo.delete(trashId); + } } class ITrashListenerImpl extends ITrashListener { diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart b/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart index 7524a66bad..983d454eeb 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/trash/trash_page.dart @@ -52,37 +52,45 @@ class _TrashStackPageState extends State { @override Widget build(BuildContext context) { final theme = context.watch(); + const horizontalPadding = 80.0; return SizedBox.expand( child: Column( children: [ _renderTopBar(theme), const VSpace(32), - Expanded( - child: ScrollbarListStack( - axis: Axis.vertical, - controller: _scrollController, - barSize: 10, - child: StyledSingleChildScrollView( - controller: ScrollController(), - axis: Axis.horizontal, - child: SizedBox( - width: TrashSizes.totalWidth, - child: CustomScrollView( - shrinkWrap: true, - physics: StyledScrollPhysics(), - controller: _scrollController, - slivers: [ - _renderListHeader(context), - _renderListBody(context), - ], - ), - ), - ), - ), - ), + _renderTrashList(context), ], mainAxisAlignment: MainAxisAlignment.start, - ).padding(horizontal: 80, vertical: 48), + ).padding(horizontal: horizontalPadding, vertical: 48), + ); + } + + Widget _renderTrashList(BuildContext context) { + 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(), + axis: Axis.horizontal, + child: SizedBox( + width: TrashSizes.totalWidth, + child: CustomScrollView( + shrinkWrap: true, + physics: StyledScrollPhysics(), + controller: _scrollController, + slivers: [ + _renderListHeader(context), + _renderListBody(context), + ], + ), + ), + ), + ), ); } @@ -99,7 +107,7 @@ class _TrashStackPageState extends State { text: const FlowyText.medium('Restore all', fontSize: 12), icon: svg('editor/restore'), hoverColor: theme.hover, - onTap: () {}, + onTap: () => context.read().add(const TrashEvent.restoreAll()), ), ), const HSpace(6), @@ -109,7 +117,7 @@ class _TrashStackPageState extends State { text: const FlowyText.medium('Delete all', fontSize: 12), icon: svg('editor/delete'), hoverColor: theme.hover, - onTap: () {}, + onTap: () => context.read().add(const TrashEvent.deleteAll()), ), ) ], @@ -133,16 +141,18 @@ class _TrashStackPageState extends State { return SliverList( delegate: SliverChildBuilderDelegate( (BuildContext context, int index) { + final object = state.objects[index]; return SizedBox( height: 42, child: TrashCell( - object: state.objects[index], - onRestore: () {}, - onDelete: () {}, + object: object, + onRestore: () => context.read().add(TrashEvent.putback(object.id)), + onDelete: () => context.read().add(TrashEvent.delete(object.id)), ), ); }, childCount: state.objects.length, + addAutomaticKeepAlives: false, ), ); }, diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart index c06b90a1b8..d3c7d90bdc 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/sizes.dart @@ -1,5 +1,6 @@ class TrashSizes { - static double scale = 1; + static double scale = 0.8; + static double get headerHeight => 60 * scale; static double get fileNameWidth => 320 * scale; static double get lashModifyWidth => 230 * scale; static double get createTimeWidth => 230 * scale; diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart index 94d1a70f62..8fee97f7be 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_cell.dart @@ -32,6 +32,7 @@ class TrashCell extends StatelessWidget { onPressed: onDelete, icon: svg("editor/delete"), ), + const HSpace(20), ], ); } diff --git a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart index f20511b937..f3f7a57a0c 100644 --- a/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart +++ b/app_flowy/lib/workspace/presentation/stack_page/trash/widget/trash_header.dart @@ -14,10 +14,10 @@ class TrashHeaderDelegate extends SliverPersistentHeaderDelegate { } @override - double get maxExtent => 60; + double get maxExtent => TrashSizes.headerHeight; @override - double get minExtent => 60; + double get minExtent => TrashSizes.headerHeight; @override bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) { diff --git a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart b/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart index 6a668f6a02..7a8caa32cf 100644 --- a/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart +++ b/app_flowy/lib/workspace/presentation/widgets/menu/menu.dart @@ -1,6 +1,7 @@ import 'package:app_flowy/workspace/presentation/widgets/menu/widget/top_bar.dart'; import 'package:dartz/dartz.dart'; import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flowy_sdk/protobuf/flowy-user/user_profile.pb.dart'; @@ -175,21 +176,26 @@ class MenuList extends StatelessWidget { return ExpandableTheme( data: ExpandableThemeData(useInkWell: true, animationDuration: Durations.medium), child: Expanded( - child: ListView.separated( - itemCount: menuItems.length, - separatorBuilder: (context, index) { - if (index == 0) { - return const VSpace(29); - } else { - return const VSpace(24); - } - }, - physics: const BouncingScrollPhysics(), - itemBuilder: (BuildContext context, int index) { - return menuItems[index]; - }, + child: ScrollConfiguration( + behavior: const ScrollBehavior(), + child: ListView.separated( + itemCount: menuItems.length, + separatorBuilder: (context, index) { + if (index == 0) { + return const VSpace(29); + } else { + return const VSpace(24); + } + }, + physics: StyledScrollPhysics(), + itemBuilder: (BuildContext context, int index) { + return menuItems[index]; + }, + ), ), ), ); } } + +class _NoGlowBehavior extends ScrollBehavior {} diff --git a/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart b/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart index faf2570949..2f3accc884 100644 --- a/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart +++ b/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scroll_bar.dart @@ -56,14 +56,6 @@ class ScrollbarState extends State { super.didUpdateWidget(oldWidget); } -// void calculateSize() { -// //[SB] Only hack I can find to make the ScrollController update it's maxExtents. -// //Call this whenever the content changes, so the scrollbar can recalculate it's size -// widget.controller.jumpTo(widget.controller.position.pixels + 1); -// Future.microtask(() => widget.controller -// .animateTo(widget.controller.position.pixels - 1, duration: 100.milliseconds, curve: Curves.linear)); -// } - @override Widget build(BuildContext context) { final theme = context.watch(); @@ -100,8 +92,7 @@ class ScrollbarState extends State { // Calculate the alignment for the handle, this is a value between 0 and 1, // it automatically takes the handle size into acct // ignore: omit_local_variable_types - double handleAlignment = - maxExtent == 0 ? 0 : widget.controller.offset / maxExtent; + double handleAlignment = maxExtent == 0 ? 0 : widget.controller.offset / maxExtent; // Convert handle alignment from [0, 1] to [-1, 1] handleAlignment *= 2.0; @@ -116,13 +107,9 @@ class ScrollbarState extends State { // Hide the handle if content is < the viewExtent var showHandle = contentExtent > _viewExtent && contentExtent > 0; // Handle color - var handleColor = widget.handleColor ?? - (theme.isDark ? theme.bg2.withOpacity(.2) : theme.bg2); + var handleColor = widget.handleColor ?? (theme.isDark ? theme.bg2.withOpacity(.2) : theme.bg2); // Track color - var trackColor = widget.trackColor ?? - (theme.isDark - ? theme.bg2.withOpacity(.1) - : theme.bg2.withOpacity(.3)); + var trackColor = widget.trackColor ?? (theme.isDark ? theme.bg2.withOpacity(.1) : theme.bg2.withOpacity(.3)); //Layout the stack, it just contains a child, and return Stack(children: [ @@ -132,12 +119,8 @@ class ScrollbarState extends State { alignment: const Alignment(1, 1), child: Container( color: trackColor, - width: widget.axis == Axis.vertical - ? widget.size - : double.infinity, - height: widget.axis == Axis.horizontal - ? widget.size - : double.infinity, + width: widget.axis == Axis.vertical ? widget.size : double.infinity, + height: widget.axis == Axis.horizontal ? widget.size : double.infinity, ), ), @@ -154,14 +137,10 @@ class ScrollbarState extends State { // HANDLE SHAPE child: MouseHoverBuilder( builder: (_, isHovered) => Container( - width: - widget.axis == Axis.vertical ? widget.size : handleExtent, - height: widget.axis == Axis.horizontal - ? widget.size - : handleExtent, + width: widget.axis == Axis.vertical ? widget.size : handleExtent, + height: widget.axis == Axis.horizontal ? widget.size : handleExtent, decoration: BoxDecoration( - color: handleColor.withOpacity(isHovered ? 1 : .85), - borderRadius: Corners.s3Border), + color: handleColor.withOpacity(isHovered ? 1 : .85), borderRadius: Corners.s3Border), ), ), ), @@ -173,19 +152,15 @@ class ScrollbarState extends State { void _handleHorizontalDrag(DragUpdateDetails details) { var pos = widget.controller.offset; - var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) / - _viewExtent; - widget.controller.jumpTo((pos + details.delta.dx * pxRatio) - .clamp(0.0, widget.controller.position.maxScrollExtent)); + var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) / _viewExtent; + widget.controller.jumpTo((pos + details.delta.dx * pxRatio).clamp(0.0, widget.controller.position.maxScrollExtent)); widget.onDrag?.call(details.delta.dx); } void _handleVerticalDrag(DragUpdateDetails details) { var pos = widget.controller.offset; - var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) / - _viewExtent; - widget.controller.jumpTo((pos + details.delta.dy * pxRatio) - .clamp(0.0, widget.controller.position.maxScrollExtent)); + var pxRatio = (widget.controller.position.maxScrollExtent + _viewExtent) / _viewExtent; + widget.controller.jumpTo((pos + details.delta.dy * pxRatio).clamp(0.0, widget.controller.position.maxScrollExtent)); widget.onDrag?.call(details.delta.dy); } } diff --git a/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart b/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart index 7a7626e51e..d548dc8f64 100644 --- a/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart +++ b/app_flowy/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_scrollview.dart @@ -9,6 +9,7 @@ class StyledSingleChildScrollView extends StatefulWidget { final Color? trackColor; final Color? handleColor; final ScrollController? controller; + final EdgeInsets? scrollbarPadding; final Widget? child; @@ -20,6 +21,7 @@ class StyledSingleChildScrollView extends StatefulWidget { this.trackColor, this.handleColor, this.controller, + this.scrollbarPadding, }) : super(key: key); @override @@ -55,6 +57,7 @@ class _StyledSingleChildScrollViewState extends State