[flutter]: fix some ui bugs

This commit is contained in:
appflowy 2021-10-14 22:58:20 +08:00
parent 6e8ae0eca9
commit 33b2eae174
11 changed files with 629 additions and 82 deletions

View File

@ -26,6 +26,16 @@ class TrashBloc extends Bloc<TrashEvent, TrashState> {
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<TrashEvent, TrashState> {
class TrashEvent with _$TrashEvent {
const factory TrashEvent.initial() = Initial;
const factory TrashEvent.didReceiveTrash(List<Trash> 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

View File

@ -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<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<Putback> get copyWith =>
_$PutbackCopyWithImpl<Putback>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<Putback> 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<Delete> get copyWith =>
_$DeleteCopyWithImpl<Delete>(this, _$identity);
@override
@optionalTypeArgs
TResult when<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<Delete> 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<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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<TResult extends Object?>({
required TResult Function() initial,
required TResult Function(List<Trash> 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 extends Object?>({
TResult Function()? initial,
TResult Function(List<Trash> 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<TResult extends Object?>({
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 extends Object?>({
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();

View File

@ -5,6 +5,10 @@ import 'package:flowy_sdk/protobuf/flowy-workspace/trash_create.pb.dart';
abstract class ITrash {
Future<Either<List<Trash>, WorkspaceError>> readTrash();
Future<Either<Unit, WorkspaceError>> putback(String trashId);
Future<Either<Unit, WorkspaceError>> delete(String trashId);
}
typedef TrashUpdatedCallback = void Function(Either<List<Trash>, WorkspaceError> trashOrFailed);

View File

@ -18,6 +18,16 @@ class ITrashImpl implements ITrash {
);
});
}
@override
Future<Either<Unit, WorkspaceError>> putback(String trashId) {
return repo.putback(trashId);
}
@override
Future<Either<Unit, WorkspaceError>> delete(String trashId) {
return repo.delete(trashId);
}
}
class ITrashListenerImpl extends ITrashListener {

View File

@ -52,37 +52,45 @@ class _TrashStackPageState extends State<TrashStackPage> {
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
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<TrashStackPage> {
text: const FlowyText.medium('Restore all', fontSize: 12),
icon: svg('editor/restore'),
hoverColor: theme.hover,
onTap: () {},
onTap: () => context.read<TrashBloc>().add(const TrashEvent.restoreAll()),
),
),
const HSpace(6),
@ -109,7 +117,7 @@ class _TrashStackPageState extends State<TrashStackPage> {
text: const FlowyText.medium('Delete all', fontSize: 12),
icon: svg('editor/delete'),
hoverColor: theme.hover,
onTap: () {},
onTap: () => context.read<TrashBloc>().add(const TrashEvent.deleteAll()),
),
)
],
@ -133,16 +141,18 @@ class _TrashStackPageState extends State<TrashStackPage> {
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<TrashBloc>().add(TrashEvent.putback(object.id)),
onDelete: () => context.read<TrashBloc>().add(TrashEvent.delete(object.id)),
),
);
},
childCount: state.objects.length,
addAutomaticKeepAlives: false,
),
);
},

View File

@ -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;

View File

@ -32,6 +32,7 @@ class TrashCell extends StatelessWidget {
onPressed: onDelete,
icon: svg("editor/delete"),
),
const HSpace(20),
],
);
}

View File

@ -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) {

View File

@ -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 {}

View File

@ -56,14 +56,6 @@ class ScrollbarState extends State<StyledScrollbar> {
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<AppTheme>();
@ -100,8 +92,7 @@ class ScrollbarState extends State<StyledScrollbar> {
// 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<StyledScrollbar> {
// 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: <Widget>[
@ -132,12 +119,8 @@ class ScrollbarState extends State<StyledScrollbar> {
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<StyledScrollbar> {
// 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<StyledScrollbar> {
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);
}
}

View File

@ -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<StyledSingleChildScrollVie
contentSize: widget.contentSize,
axis: widget.axis,
controller: scrollController,
scrollbarPadding: widget.scrollbarPadding,
barSize: 12,
trackColor: widget.trackColor,
handleColor: widget.handleColor,