Ver Fonte

chore: auto resize row height

appflowy há 3 anos atrás
pai
commit
d4de5767a6

+ 11 - 0
frontend/app_flowy/lib/workspace/application/grid/row/row_service.dart

@@ -21,6 +21,17 @@ class RowService {
     return GridEventCreateRow(payload).send();
   }
 
+  Future<Either<Unit, FlowyError>> moveRow(String rowId, int fromIndex, int toIndex) {
+    final payload = MoveItemPayload.create()
+      ..gridId = gridId
+      ..itemId = rowId
+      ..ty = MoveItemType.MoveRow
+      ..fromIndex = fromIndex
+      ..toIndex = toIndex;
+
+    return GridEventMoveItem(payload).send();
+  }
+
   Future<Either<Row, FlowyError>> getRow() {
     final payload = RowIdentifierPayload.create()
       ..gridId = gridId

+ 6 - 10
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/grid_page.dart

@@ -107,7 +107,7 @@ class _FlowyGridState extends State<FlowyGrid> {
           crossAxisAlignment: CrossAxisAlignment.start,
           children: [
             const _GridToolbarAdaptor(),
-            _gridHeader(context, state.gridId, contentWidth),
+            _gridHeader(context, state.gridId),
             Flexible(child: child),
           ],
         );
@@ -147,16 +147,12 @@ class _FlowyGridState extends State<FlowyGrid> {
     );
   }
 
-  Widget _gridHeader(BuildContext context, String gridId, double contentWidth) {
+  Widget _gridHeader(BuildContext context, String gridId) {
     final fieldCache = context.read<GridBloc>().fieldCache;
-
-    return SizedBox(
-      width: contentWidth,
-      child: GridHeaderSliverAdaptor(
-        gridId: gridId,
-        fieldCache: fieldCache,
-        anchorScrollController: headerScrollController,
-      ),
+    return GridHeaderSliverAdaptor(
+      gridId: gridId,
+      fieldCache: fieldCache,
+      anchorScrollController: headerScrollController,
     );
   }
 }

+ 1 - 3
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/cell_container.dart

@@ -33,9 +33,7 @@ class CellContainer extends StatelessWidget {
       child: Consumer<CellStateNotifier>(
         builder: (context, state, _) {
           return Container(
-            constraints: BoxConstraints(
-              maxWidth: width,
-            ),
+            constraints: BoxConstraints(maxWidth: width, maxHeight: 42),
             decoration: _makeBoxDecoration(context, state),
             padding: GridSize.cellContentInsets,
             child: Center(child: child),

+ 69 - 36
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/field_cell.dart

@@ -6,6 +6,7 @@ import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
+import 'package:flowy_sdk/log.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'field_type_extension.dart';
@@ -28,49 +29,19 @@ class GridFieldCell extends StatelessWidget {
           final button = FlowyButton(
             hoverColor: theme.shader6,
             onTap: () => _showActionSheet(context),
-            // rightIcon: svgWidget("editor/details", color: theme.iconColor),
             leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor),
             text: FlowyText.medium(state.field.name, fontSize: 12),
             padding: GridSize.cellContentInsets,
           );
 
-          final line = InkWell(
-            onTap: () {},
-            child: GestureDetector(
-              behavior: HitTestBehavior.opaque,
-              onHorizontalDragCancel: () {},
-              onHorizontalDragUpdate: (value) {
-                context.read<FieldCellBloc>().add(FieldCellEvent.updateWidth(value.delta.dx));
-              },
-              child: FlowyHover(
-                style: HoverStyle(
-                  hoverColor: theme.main1,
-                  borderRadius: BorderRadius.zero,
-                  contentMargin: const EdgeInsets.only(left: 5),
-                ),
-                builder: (_, onHover) => const SizedBox(width: 2),
-              ),
-            ),
-          );
-
-          final borderSide = BorderSide(color: theme.shader4, width: 0.4);
-          final decoration = BoxDecoration(
-              border: Border(
-            top: borderSide,
-            right: borderSide,
-            bottom: borderSide,
-          ));
+          const line = Positioned(top: 0, bottom: 0, right: 0, child: _DragToExpandLine());
 
-          return Container(
+          return _CellContainer(
             width: state.field.width.toDouble(),
-            decoration: decoration,
-            child: ConstrainedBox(
-              constraints: const BoxConstraints.expand(),
-              child: Stack(
-                alignment: Alignment.centerRight,
-                fit: StackFit.expand,
-                children: [button, Positioned(top: 0, bottom: 0, right: 0, child: line)],
-              ),
+            child: Stack(
+              alignment: Alignment.centerRight,
+              fit: StackFit.expand,
+              children: [button, line],
             ),
           );
         },
@@ -98,3 +69,65 @@ class GridFieldCell extends StatelessWidget {
     ).show(context);
   }
 }
+
+class _CellContainer extends StatelessWidget {
+  final Widget child;
+  final double width;
+  const _CellContainer({
+    required this.child,
+    required this.width,
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final theme = context.watch<AppTheme>();
+    final borderSide = BorderSide(color: theme.shader4, width: 0.4);
+    final decoration = BoxDecoration(
+        border: Border(
+      top: borderSide,
+      right: borderSide,
+      bottom: borderSide,
+    ));
+
+    return Container(
+      width: width,
+      decoration: decoration,
+      child: ConstrainedBox(constraints: const BoxConstraints.expand(), child: child),
+    );
+  }
+}
+
+class _DragToExpandLine extends StatelessWidget {
+  const _DragToExpandLine({
+    Key? key,
+  }) : super(key: key);
+
+  @override
+  Widget build(BuildContext context) {
+    final theme = context.watch<AppTheme>();
+
+    return InkWell(
+      onTap: () {},
+      child: GestureDetector(
+        behavior: HitTestBehavior.opaque,
+        onHorizontalDragCancel: () {},
+        onHorizontalDragUpdate: (value) {
+          // context.read<FieldCellBloc>().add(FieldCellEvent.updateWidth(value.delta.dx));
+          Log.info(value);
+        },
+        onHorizontalDragEnd: (end) {
+          Log.info(end);
+        },
+        child: FlowyHover(
+          style: HoverStyle(
+            hoverColor: theme.main1,
+            borderRadius: BorderRadius.zero,
+            contentMargin: const EdgeInsets.only(left: 5),
+          ),
+          builder: (_, onHover) => const SizedBox(width: 2),
+        ),
+      ),
+    );
+  }
+}

+ 35 - 29
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/grid_header.dart

@@ -32,15 +32,21 @@ class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
   @override
   Widget build(BuildContext context) {
     return BlocProvider(
-      create: (context) =>
-          getIt<GridHeaderBloc>(param1: widget.gridId, param2: widget.fieldCache)..add(const GridHeaderEvent.initial()),
+      create: (context) {
+        final bloc = getIt<GridHeaderBloc>(param1: widget.gridId, param2: widget.fieldCache);
+        bloc.add(const GridHeaderEvent.initial());
+        return bloc;
+      },
       child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
         buildWhen: (previous, current) => previous.fields.length != current.fields.length,
         builder: (context, state) {
           return SingleChildScrollView(
             scrollDirection: Axis.horizontal,
             controller: widget.anchorScrollController,
-            child: SizedBox(height: GridSize.headerHeight, child: _GridHeader(gridId: widget.gridId)),
+            child: SizedBox(
+              height: GridSize.headerHeight,
+              child: _GridHeader(gridId: widget.gridId),
+            ),
           );
 
           // return SliverPersistentHeader(
@@ -54,32 +60,6 @@ class _GridHeaderSliverAdaptorState extends State<GridHeaderSliverAdaptor> {
   }
 }
 
-class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate {
-  final String gridId;
-  final List<Field> fields;
-
-  SliverHeaderDelegateImplementation({required this.gridId, required this.fields});
-
-  @override
-  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
-    return _GridHeader(gridId: gridId);
-  }
-
-  @override
-  double get maxExtent => GridSize.headerHeight;
-
-  @override
-  double get minExtent => GridSize.headerHeight;
-
-  @override
-  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
-    if (oldDelegate is SliverHeaderDelegateImplementation) {
-      return fields.length != oldDelegate.fields.length;
-    }
-    return true;
-  }
-}
-
 class _GridHeader extends StatefulWidget {
   final String gridId;
   const _GridHeader({Key? key, required this.gridId}) : super(key: key);
@@ -177,3 +157,29 @@ class CreateFieldButton extends StatelessWidget {
     );
   }
 }
+
+class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate {
+  final String gridId;
+  final List<Field> fields;
+
+  SliverHeaderDelegateImplementation({required this.gridId, required this.fields});
+
+  @override
+  Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
+    return _GridHeader(gridId: gridId);
+  }
+
+  @override
+  double get maxExtent => GridSize.headerHeight;
+
+  @override
+  double get minExtent => GridSize.headerHeight;
+
+  @override
+  bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
+    if (oldDelegate is SliverHeaderDelegateImplementation) {
+      return fields.length != oldDelegate.fields.length;
+    }
+    return true;
+  }
+}

+ 9 - 4
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/row/grid_row.dart

@@ -44,10 +44,11 @@ class _GridRowWidgetState extends State<GridRowWidget> {
           child: BlocBuilder<RowBloc, RowState>(
             buildWhen: (p, c) => p.rowData.height != c.rowData.height,
             builder: (context, state) {
-              return SizedBox(
-                height: _rowBloc.state.rowData.height,
+              return LimitedBox(
+                maxHeight: 200,
                 child: Row(
-                  crossAxisAlignment: CrossAxisAlignment.stretch,
+                  mainAxisSize: MainAxisSize.max,
+                  crossAxisAlignment: CrossAxisAlignment.center,
                   children: const [
                     _RowLeading(),
                     _RowCells(),
@@ -147,7 +148,11 @@ class _RowCells extends StatelessWidget {
       buildWhen: (previous, current) => previous.cellDataMap != current.cellDataMap,
       builder: (context, state) {
         final List<Widget> children = state.cellDataMap.fold(() => [], _toCells);
-        return Row(children: children);
+        return Row(
+          mainAxisSize: MainAxisSize.min,
+          mainAxisAlignment: MainAxisAlignment.center,
+          children: children,
+        );
       },
     );
   }

+ 15 - 8
frontend/rust-lib/flowy-grid/src/services/block_meta_editor.rs

@@ -51,16 +51,16 @@ impl ClientGridBlockMetaEditor {
         let mut row_count = 0;
         let mut row_index = None;
         let _ = self
-            .modify(|pad| {
+            .modify(|block_pad| {
                 if let Some(start_row_id) = start_row_id.as_ref() {
-                    match pad.index_of_row(start_row_id) {
+                    match block_pad.index_of_row(start_row_id) {
                         None => {}
                         Some(index) => row_index = Some(index + 1),
                     }
                 }
 
-                let change = pad.add_row_meta(row, start_row_id)?;
-                row_count = pad.number_of_rows();
+                let change = block_pad.add_row_meta(row, start_row_id)?;
+                row_count = block_pad.number_of_rows();
                 Ok(change)
             })
             .await?;
@@ -71,9 +71,9 @@ impl ClientGridBlockMetaEditor {
     pub async fn delete_rows(&self, ids: Vec<Cow<'_, String>>) -> FlowyResult<i32> {
         let mut row_count = 0;
         let _ = self
-            .modify(|pad| {
-                let changeset = pad.delete_rows(ids)?;
-                row_count = pad.number_of_rows();
+            .modify(|block_pad| {
+                let changeset = block_pad.delete_rows(ids)?;
+                row_count = block_pad.number_of_rows();
                 Ok(changeset)
             })
             .await?;
@@ -81,7 +81,14 @@ impl ClientGridBlockMetaEditor {
     }
 
     pub async fn update_row(&self, changeset: RowMetaChangeset) -> FlowyResult<()> {
-        let _ = self.modify(|pad| Ok(pad.update_row(changeset)?)).await?;
+        let _ = self.modify(|block_pad| Ok(block_pad.update_row(changeset)?)).await?;
+        Ok(())
+    }
+
+    pub async fn move_row(&self, row_id: &str, from: usize, to: usize) -> FlowyResult<()> {
+        let _ = self
+            .modify(|block_pad| Ok(block_pad.move_row(row_id, from, to)?))
+            .await?;
         Ok(())
     }
 

+ 26 - 0
frontend/rust-lib/flowy-grid/src/services/block_meta_manager.rs

@@ -154,6 +154,32 @@ impl GridBlockMetaEditorManager {
         Ok(changesets)
     }
 
+    pub(crate) async fn move_row(&self, row_id: &str, from: usize, to: usize) -> FlowyResult<()> {
+        let editor = self.get_editor_from_row_id(row_id).await?;
+        let _ = editor.move_row(row_id, from, to).await?;
+
+        match editor.get_row_metas(Some(vec![Cow::Borrowed(row_id)])).await?.pop() {
+            None => {}
+            Some(row_meta) => {
+                let row_order = RowOrder::from(&row_meta);
+                let insert_row = IndexRowOrder {
+                    row_order: row_order.clone(),
+                    index: Some(to as i32),
+                };
+                let notified_changeset = GridRowsChangeset {
+                    block_id: editor.block_id.clone(),
+                    inserted_rows: vec![insert_row],
+                    deleted_rows: vec![row_order],
+                    updated_rows: vec![],
+                };
+
+                let _ = self.notify_did_update_rows(notified_changeset).await?;
+            }
+        }
+
+        Ok(())
+    }
+
     pub async fn update_cell(&self, changeset: CellChangeset) -> FlowyResult<()> {
         let row_id = changeset.row_id.clone();
         let editor = self.get_editor_from_row_id(&row_id).await?;

+ 7 - 4
frontend/rust-lib/flowy-grid/src/services/grid_editor.rs

@@ -388,7 +388,7 @@ impl ClientGridEditor {
                 self.move_field(&params.item_id, params.from_index, params.to_index)
                     .await
             }
-            MoveItemType::MoveRow => self.move_row(params.from_index, params.to_index, &params.item_id).await,
+            MoveItemType::MoveRow => self.move_row(&params.item_id, params.from_index, params.to_index).await,
         }
     }
 
@@ -411,9 +411,12 @@ impl ClientGridEditor {
         Ok(())
     }
 
-    pub async fn move_row(&self, from: i32, to: i32, row_id: &str) -> FlowyResult<()> {
-        // GridRowsChangeset
-        todo!()
+    pub async fn move_row(&self, row_id: &str, from: i32, to: i32) -> FlowyResult<()> {
+        let _ = self
+            .block_meta_manager
+            .move_row(row_id, from as usize, to as usize)
+            .await?;
+        Ok(())
     }
 
     pub async fn delta_bytes(&self) -> Bytes {

+ 13 - 0
shared-lib/flowy-sync/src/client_grid/grid_block_meta_pad.rs

@@ -149,6 +149,19 @@ impl GridBlockMetaPad {
         })
     }
 
+    pub fn move_row(&mut self, row_id: &str, from: usize, to: usize) -> CollaborateResult<Option<GridBlockMetaChange>> {
+        self.modify(|row_metas| {
+            if let Some(position) = row_metas.iter().position(|row_meta| row_meta.id == row_id) {
+                debug_assert_eq!(from, position);
+                let row_meta = row_metas.remove(position);
+                row_metas.insert(to, row_meta);
+                Ok(Some(()))
+            } else {
+                Ok(None)
+            }
+        })
+    }
+
     pub fn modify<F>(&mut self, f: F) -> CollaborateResult<Option<GridBlockMetaChange>>
     where
         F: for<'a> FnOnce(&'a mut Vec<Arc<RowMeta>>) -> CollaborateResult<Option<()>>,