mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: repalce sliver header with single scroll view
This commit is contained in:
parent
d71e0de8c3
commit
6dbb708991
@ -1,3 +1,4 @@
|
|||||||
|
import 'package:app_flowy/workspace/application/grid/field/field_service.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
@ -7,13 +8,14 @@ import 'grid_service.dart';
|
|||||||
part 'grid_header_bloc.freezed.dart';
|
part 'grid_header_bloc.freezed.dart';
|
||||||
|
|
||||||
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||||
// final FieldService _fieldService;
|
final FieldService _fieldService;
|
||||||
final GridFieldCache fieldCache;
|
final GridFieldCache fieldCache;
|
||||||
|
|
||||||
GridHeaderBloc({
|
GridHeaderBloc({
|
||||||
required String gridId,
|
required String gridId,
|
||||||
required this.fieldCache,
|
required this.fieldCache,
|
||||||
}) : super(GridHeaderState.initial(fieldCache.clonedFields)) {
|
}) : _fieldService = FieldService(gridId: gridId),
|
||||||
|
super(GridHeaderState.initial(fieldCache.clonedFields)) {
|
||||||
on<GridHeaderEvent>(
|
on<GridHeaderEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
@ -23,6 +25,7 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
|||||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||||
emit(state.copyWith(fields: value.fields));
|
emit(state.copyWith(fields: value.fields));
|
||||||
},
|
},
|
||||||
|
moveField: (_MoveField value) {},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -46,6 +49,7 @@ class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
|||||||
class GridHeaderEvent with _$GridHeaderEvent {
|
class GridHeaderEvent with _$GridHeaderEvent {
|
||||||
const factory GridHeaderEvent.initial() = _InitialHeader;
|
const factory GridHeaderEvent.initial() = _InitialHeader;
|
||||||
const factory GridHeaderEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
|
const factory GridHeaderEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
|
||||||
|
const factory GridHeaderEvent.moveField(int fromIndex, int toIndex) = _MoveField;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
|
@ -1,21 +1,28 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
|
||||||
|
|
||||||
class GridScrollController {
|
class GridScrollController {
|
||||||
final ScrollController _verticalController = ScrollController();
|
final LinkedScrollControllerGroup _scrollGroupContorller;
|
||||||
final ScrollController _horizontalController = ScrollController();
|
final ScrollController verticalController;
|
||||||
|
final ScrollController horizontalController;
|
||||||
|
|
||||||
ScrollController get verticalController => _verticalController;
|
final List<ScrollController> _linkHorizontalControllers = [];
|
||||||
ScrollController get horizontalController => _horizontalController;
|
|
||||||
|
|
||||||
GridScrollController();
|
GridScrollController({required LinkedScrollControllerGroup scrollGroupContorller})
|
||||||
|
: _scrollGroupContorller = scrollGroupContorller,
|
||||||
|
verticalController = ScrollController(),
|
||||||
|
horizontalController = scrollGroupContorller.addAndGet();
|
||||||
|
|
||||||
// final SelectionChangeCallback? onSelectionChanged;
|
ScrollController linkHorizontalController() {
|
||||||
|
final controller = _scrollGroupContorller.addAndGet();
|
||||||
// final ShouldApplySelection? shouldApplySelection;
|
_linkHorizontalControllers.add(controller);
|
||||||
|
return controller;
|
||||||
// final ScrollCallback? onScroll;
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
for (final controller in _linkHorizontalControllers) {
|
||||||
|
controller.dispose();
|
||||||
|
}
|
||||||
verticalController.dispose();
|
verticalController.dispose();
|
||||||
horizontalController.dispose();
|
horizontalController.dispose();
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@ import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart' show Field;
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:linked_scroll_controller/linked_scroll_controller.dart';
|
||||||
import 'controller/grid_scroll.dart';
|
import 'controller/grid_scroll.dart';
|
||||||
import 'layout/layout.dart';
|
import 'layout/layout.dart';
|
||||||
import 'layout/sizes.dart';
|
import 'layout/sizes.dart';
|
||||||
@ -73,17 +74,23 @@ class FlowyGrid extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _FlowyGridState extends State<FlowyGrid> {
|
class _FlowyGridState extends State<FlowyGrid> {
|
||||||
final _scrollController = GridScrollController();
|
final _scrollController = GridScrollController(scrollGroupContorller: LinkedScrollControllerGroup());
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
_scrollController.dispose();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocBuilder<GridBloc, GridState>(
|
return BlocBuilder<GridBloc, GridState>(
|
||||||
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
|
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
|
final contentWidth = GridLayout.headerWidth(state.fields);
|
||||||
final child = _wrapScrollView(
|
final child = _wrapScrollView(
|
||||||
state.fields,
|
contentWidth,
|
||||||
[
|
[
|
||||||
_GridHeader(gridId: state.gridId, fields: state.fields),
|
|
||||||
const _GridRows(),
|
const _GridRows(),
|
||||||
const _GridFooter(),
|
const _GridFooter(),
|
||||||
],
|
],
|
||||||
@ -91,6 +98,7 @@ class _FlowyGridState extends State<FlowyGrid> {
|
|||||||
|
|
||||||
return Column(children: [
|
return Column(children: [
|
||||||
const _GridToolbarAdaptor(),
|
const _GridToolbarAdaptor(),
|
||||||
|
_gridHeader(context, state.gridId, contentWidth),
|
||||||
Flexible(child: child),
|
Flexible(child: child),
|
||||||
]);
|
]);
|
||||||
},
|
},
|
||||||
@ -98,7 +106,7 @@ class _FlowyGridState extends State<FlowyGrid> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _wrapScrollView(
|
Widget _wrapScrollView(
|
||||||
List<Field> fields,
|
double contentWidth,
|
||||||
List<Widget> slivers,
|
List<Widget> slivers,
|
||||||
) {
|
) {
|
||||||
final verticalScrollView = ScrollConfiguration(
|
final verticalScrollView = ScrollConfiguration(
|
||||||
@ -111,7 +119,7 @@ class _FlowyGridState extends State<FlowyGrid> {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final sizedVerticalScrollView = SizedBox(
|
final sizedVerticalScrollView = SizedBox(
|
||||||
width: GridLayout.headerWidth(fields),
|
width: contentWidth,
|
||||||
child: verticalScrollView,
|
child: verticalScrollView,
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -128,6 +136,19 @@ class _FlowyGridState extends State<FlowyGrid> {
|
|||||||
child: horizontalScrollView,
|
child: horizontalScrollView,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Widget _gridHeader(BuildContext context, String gridId, double contentWidth) {
|
||||||
|
final fieldCache = context.read<GridBloc>().fieldCache;
|
||||||
|
|
||||||
|
return SizedBox(
|
||||||
|
width: contentWidth,
|
||||||
|
child: GridHeaderSliverAdaptor(
|
||||||
|
gridId: gridId,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
anchorScrollController: _scrollController.linkHorizontalController(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GridToolbarAdaptor extends StatelessWidget {
|
class _GridToolbarAdaptor extends StatelessWidget {
|
||||||
@ -149,18 +170,6 @@ class _GridToolbarAdaptor extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _GridHeader extends StatelessWidget {
|
|
||||||
final String gridId;
|
|
||||||
final List<Field> fields;
|
|
||||||
const _GridHeader({Key? key, required this.gridId, required this.fields}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
final fieldCache = context.read<GridBloc>().fieldCache;
|
|
||||||
return GridHeaderSliverAdaptor(gridId: gridId, fieldCache: fieldCache);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _GridRows extends StatefulWidget {
|
class _GridRows extends StatefulWidget {
|
||||||
const _GridRows({Key? key}) : super(key: key);
|
const _GridRows({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -13,25 +13,41 @@ import 'package:reorderables/reorderables.dart';
|
|||||||
import 'field_editor.dart';
|
import 'field_editor.dart';
|
||||||
import 'field_cell.dart';
|
import 'field_cell.dart';
|
||||||
|
|
||||||
class GridHeaderSliverAdaptor extends StatelessWidget {
|
class GridHeaderSliverAdaptor extends StatefulWidget {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final GridFieldCache fieldCache;
|
final GridFieldCache fieldCache;
|
||||||
|
final ScrollController anchorScrollController;
|
||||||
|
const GridHeaderSliverAdaptor({
|
||||||
|
required this.gridId,
|
||||||
|
required this.fieldCache,
|
||||||
|
required this.anchorScrollController,
|
||||||
|
Key? key,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
const GridHeaderSliverAdaptor({required this.gridId, required this.fieldCache, Key? key}) : super(key: key);
|
@override
|
||||||
|
State<GridHeaderSliverAdaptor> createState() => _GridHeaderSliverAdaptorState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) =>
|
create: (context) =>
|
||||||
getIt<GridHeaderBloc>(param1: gridId, param2: fieldCache)..add(const GridHeaderEvent.initial()),
|
getIt<GridHeaderBloc>(param1: widget.gridId, param2: widget.fieldCache)..add(const GridHeaderEvent.initial()),
|
||||||
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
|
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
|
||||||
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
|
buildWhen: (previous, current) => previous.fields.length != current.fields.length,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
return SliverPersistentHeader(
|
return SingleChildScrollView(
|
||||||
delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: state.fields),
|
scrollDirection: Axis.horizontal,
|
||||||
floating: true,
|
controller: widget.anchorScrollController,
|
||||||
pinned: true,
|
child: SizedBox(height: GridSize.headerHeight, child: _GridHeader(gridId: widget.gridId)),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// return SliverPersistentHeader(
|
||||||
|
// delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: state.fields),
|
||||||
|
// floating: true,
|
||||||
|
// pinned: true,
|
||||||
|
// );
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -46,7 +62,7 @@ class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||||
return _GridHeader(gridId: gridId, fields: fields);
|
return _GridHeader(gridId: gridId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -66,13 +82,7 @@ class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate
|
|||||||
|
|
||||||
class _GridHeader extends StatefulWidget {
|
class _GridHeader extends StatefulWidget {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final List<Field> fields;
|
const _GridHeader({Key? key, required this.gridId}) : super(key: key);
|
||||||
|
|
||||||
const _GridHeader({
|
|
||||||
Key? key,
|
|
||||||
required this.gridId,
|
|
||||||
required this.fields,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<_GridHeader> createState() => _GridHeaderState();
|
State<_GridHeader> createState() => _GridHeaderState();
|
||||||
@ -93,15 +103,17 @@ class _GridHeaderState extends State<_GridHeader> {
|
|||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
color: theme.surface,
|
color: theme.surface,
|
||||||
child: ReorderableRow(
|
child: RepaintBoundary(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: ReorderableRow(
|
||||||
scrollController: ScrollController(),
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
header: const _CellLeading(),
|
scrollController: ScrollController(),
|
||||||
footer: _CellTrailing(gridId: widget.gridId),
|
header: const _CellLeading(),
|
||||||
onReorder: (int oldIndex, int newIndex) {
|
footer: _CellTrailing(gridId: widget.gridId),
|
||||||
Log.info("from $oldIndex to $newIndex");
|
onReorder: (int oldIndex, int newIndex) {
|
||||||
},
|
Log.info("from $oldIndex to $newIndex");
|
||||||
children: cells,
|
},
|
||||||
|
children: cells,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -653,6 +653,13 @@ packages:
|
|||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.4.0"
|
version: "4.4.0"
|
||||||
|
linked_scroll_controller:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: linked_scroll_controller
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.2.0"
|
||||||
lint:
|
lint:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -75,6 +75,7 @@ dependencies:
|
|||||||
fluttertoast: ^8.0.8
|
fluttertoast: ^8.0.8
|
||||||
table_calendar: ^3.0.5
|
table_calendar: ^3.0.5
|
||||||
reorderables:
|
reorderables:
|
||||||
|
linked_scroll_controller: ^0.2.0
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_lints: ^1.0.0
|
flutter_lints: ^1.0.0
|
||||||
|
Loading…
Reference in New Issue
Block a user