mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: auto expand row detail page's cell
This commit is contained in:
@ -47,13 +47,11 @@ class BlankCell extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract class GridCellWidget extends HoverWidget {
|
abstract class GridCellWidget implements FlowyHoverWidget {
|
||||||
@override
|
@override
|
||||||
final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
|
final ValueNotifier<bool> onFocus = ValueNotifier<bool>(false);
|
||||||
|
|
||||||
final GridCellRequestFocusNotifier requestFocus = GridCellRequestFocusNotifier();
|
final GridCellRequestFocusNotifier requestFocus = GridCellRequestFocusNotifier();
|
||||||
|
|
||||||
GridCellWidget({Key? key}) : super(key: key);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridCellRequestFocusNotifier extends ChangeNotifier {
|
class GridCellRequestFocusNotifier extends ChangeNotifier {
|
||||||
|
@ -6,7 +6,7 @@ import 'package:flutter/widgets.dart';
|
|||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'cell_builder.dart';
|
import 'cell_builder.dart';
|
||||||
|
|
||||||
class CheckboxCell extends GridCellWidget {
|
class CheckboxCell extends StatefulWidget with GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
CheckboxCell({
|
CheckboxCell({
|
||||||
required this.cellContextBuilder,
|
required this.cellContextBuilder,
|
||||||
@ -41,7 +41,7 @@ class _CheckboxCellState extends State<CheckboxCell> {
|
|||||||
onPressed: () => context.read<CheckboxCellBloc>().add(const CheckboxCellEvent.select()),
|
onPressed: () => context.read<CheckboxCellBloc>().add(const CheckboxCellEvent.select()),
|
||||||
iconPadding: EdgeInsets.zero,
|
iconPadding: EdgeInsets.zero,
|
||||||
icon: icon,
|
icon: icon,
|
||||||
width: 23,
|
width: 20,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
@ -7,7 +7,7 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
|
|
||||||
import 'cell_builder.dart';
|
import 'cell_builder.dart';
|
||||||
|
|
||||||
class NumberCell extends GridCellWidget {
|
class NumberCell extends StatefulWidget with GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
|
|
||||||
NumberCell({
|
NumberCell({
|
||||||
|
@ -20,7 +20,7 @@ class SelectOptionCellStyle extends GridCellStyle {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class SingleSelectCell extends GridCellWidget {
|
class SingleSelectCell extends StatefulWidget with GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
late final SelectOptionCellStyle? cellStyle;
|
||||||
|
|
||||||
@ -74,7 +74,7 @@ class _SingleSelectCellState extends State<SingleSelectCell> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//----------------------------------------------------------------
|
//----------------------------------------------------------------
|
||||||
class MultiSelectCell extends GridCellWidget {
|
class MultiSelectCell extends StatefulWidget with GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final SelectOptionCellStyle? cellStyle;
|
late final SelectOptionCellStyle? cellStyle;
|
||||||
|
|
||||||
@ -160,7 +160,7 @@ class _SelectOptionCell extends StatelessWidget {
|
|||||||
.toList();
|
.toList();
|
||||||
child = Align(
|
child = Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Wrap(children: tags, spacing: 4, runSpacing: 4),
|
child: Wrap(children: tags, spacing: 4, runSpacing: 2),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +13,7 @@ class GridTextCellStyle extends GridCellStyle {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
class GridTextCell extends GridCellWidget {
|
class GridTextCell extends StatefulWidget with GridCellWidget {
|
||||||
final GridCellContextBuilder cellContextBuilder;
|
final GridCellContextBuilder cellContextBuilder;
|
||||||
late final GridTextCellStyle? cellStyle;
|
late final GridTextCellStyle? cellStyle;
|
||||||
GridTextCell({
|
GridTextCell({
|
||||||
|
@ -71,10 +71,11 @@ class _RowDetailPageState extends State<RowDetailPage> {
|
|||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 40,
|
height: 40,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: const [Spacer(), _CloseButton()],
|
children: const [Spacer(), _CloseButton()],
|
||||||
)),
|
),
|
||||||
|
),
|
||||||
Expanded(child: _PropertyList(cellCache: widget.cellCache)),
|
Expanded(child: _PropertyList(cellCache: widget.cellCache)),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -153,24 +154,26 @@ class _RowDetailCell extends StatelessWidget {
|
|||||||
cellCache,
|
cellCache,
|
||||||
style: _buildCellStyle(theme, gridCell.field.fieldType),
|
style: _buildCellStyle(theme, gridCell.field.fieldType),
|
||||||
);
|
);
|
||||||
return SizedBox(
|
return ConstrainedBox(
|
||||||
height: 36,
|
constraints: const BoxConstraints(minHeight: 40),
|
||||||
child: Row(
|
child: IntrinsicHeight(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
SizedBox(
|
children: [
|
||||||
width: 150,
|
SizedBox(
|
||||||
child: FieldCellButton(field: gridCell.field, onTap: () => _showFieldEditor(context)),
|
width: 150,
|
||||||
),
|
child: FieldCellButton(field: gridCell.field, onTap: () => _showFieldEditor(context)),
|
||||||
const HSpace(10),
|
|
||||||
Expanded(
|
|
||||||
child: FlowyHover2(
|
|
||||||
child: cell,
|
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4),
|
|
||||||
),
|
),
|
||||||
),
|
const HSpace(10),
|
||||||
],
|
Expanded(
|
||||||
|
child: FlowyHover2(
|
||||||
|
child: cell,
|
||||||
|
contentPadding: const EdgeInsets.symmetric(horizontal: 10, vertical: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -102,14 +102,14 @@ class FlowyHoverContainer extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
abstract class HoverWidget extends StatefulWidget {
|
abstract class FlowyHoverWidget extends Widget {
|
||||||
const HoverWidget({Key? key}) : super(key: key);
|
const FlowyHoverWidget({Key? key}) : super(key: key);
|
||||||
|
|
||||||
ValueNotifier<bool> get onFocus;
|
ValueNotifier<bool>? get onFocus;
|
||||||
}
|
}
|
||||||
|
|
||||||
class FlowyHover2 extends StatefulWidget {
|
class FlowyHover2 extends StatefulWidget {
|
||||||
final Widget child;
|
final FlowyHoverWidget child;
|
||||||
final EdgeInsets contentPadding;
|
final EdgeInsets contentPadding;
|
||||||
const FlowyHover2({
|
const FlowyHover2({
|
||||||
required this.child,
|
required this.child,
|
||||||
@ -123,24 +123,30 @@ class FlowyHover2 extends StatefulWidget {
|
|||||||
|
|
||||||
class _FlowyHover2State extends State<FlowyHover2> {
|
class _FlowyHover2State extends State<FlowyHover2> {
|
||||||
late FlowyHoverState _hoverState;
|
late FlowyHoverState _hoverState;
|
||||||
|
VoidCallback? _listenerFn;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_hoverState = FlowyHoverState();
|
_hoverState = FlowyHoverState();
|
||||||
|
|
||||||
if (widget.child is HoverWidget) {
|
listener() {
|
||||||
final hoverWidget = widget.child as HoverWidget;
|
_hoverState.onFocus = widget.child.onFocus?.value ?? false;
|
||||||
hoverWidget.onFocus.addListener(() {
|
|
||||||
_hoverState.onFocus = hoverWidget.onFocus.value;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_listenerFn = listener;
|
||||||
|
widget.child.onFocus?.addListener(listener);
|
||||||
|
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_hoverState.dispose();
|
_hoverState.dispose();
|
||||||
|
|
||||||
|
if (_listenerFn != null) {
|
||||||
|
widget.child.onFocus?.removeListener(_listenerFn!);
|
||||||
|
_listenerFn = null;
|
||||||
|
}
|
||||||
super.dispose();
|
super.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -179,10 +185,7 @@ class _HoverBackground extends StatelessWidget {
|
|||||||
builder: (context, state, child) {
|
builder: (context, state, child) {
|
||||||
if (state.onHover || state.onFocus) {
|
if (state.onHover || state.onFocus) {
|
||||||
return FlowyHoverContainer(
|
return FlowyHoverContainer(
|
||||||
style: HoverStyle(
|
style: HoverStyle(borderRadius: Corners.s6Border, hoverColor: theme.shader6),
|
||||||
borderRadius: Corners.s6Border,
|
|
||||||
hoverColor: theme.shader6,
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return const SizedBox();
|
return const SizedBox();
|
||||||
|
@ -132,9 +132,12 @@ class _RoundedInputFieldState extends State<RoundedInputField> {
|
|||||||
children.add(
|
children.add(
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Padding(
|
||||||
widget.errorText,
|
padding: const EdgeInsets.symmetric(vertical: 4),
|
||||||
style: widget.style,
|
child: Text(
|
||||||
|
widget.errorText,
|
||||||
|
style: widget.style,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
proto_crates = [
|
proto_crates = [
|
||||||
"src/event_map.rs",
|
"src/event_map.rs",
|
||||||
"src/services/field/type_options",
|
"src/services/field/type_options",
|
||||||
"src/services/entities",
|
"src/entities",
|
||||||
"src/dart_notification.rs"
|
"src/dart_notification.rs"
|
||||||
]
|
]
|
||||||
event_files = ["src/event_map.rs"]
|
event_files = ["src/event_map.rs"]
|
@ -1,4 +1,4 @@
|
|||||||
use crate::services::entities::{FieldIdentifier, FieldIdentifierPayload};
|
use crate::entities::{FieldIdentifier, FieldIdentifierPayload};
|
||||||
use flowy_derive::ProtoBuf;
|
use flowy_derive::ProtoBuf;
|
||||||
use flowy_error::ErrorCode;
|
use flowy_error::ErrorCode;
|
||||||
use flowy_grid_data_model::parser::NotEmptyStr;
|
use flowy_grid_data_model::parser::NotEmptyStr;
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::entities::*;
|
||||||
use crate::manager::GridManager;
|
use crate::manager::GridManager;
|
||||||
use crate::services::entities::*;
|
|
||||||
use crate::services::field::type_options::*;
|
use crate::services::field::type_options::*;
|
||||||
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str};
|
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_json_str};
|
||||||
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
use flowy_error::{ErrorCode, FlowyError, FlowyResult};
|
||||||
|
@ -6,6 +6,7 @@ pub mod event_map;
|
|||||||
pub mod manager;
|
pub mod manager;
|
||||||
|
|
||||||
mod dart_notification;
|
mod dart_notification;
|
||||||
|
pub mod entities;
|
||||||
mod protobuf;
|
mod protobuf;
|
||||||
pub mod services;
|
pub mod services;
|
||||||
pub mod util;
|
pub mod util;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::entities::{CellIdentifier, CellIdentifierPayload};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::entities::{CellIdentifier, CellIdentifierPayload};
|
|
||||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
use crate::entities::{CellIdentifier, CellIdentifierPayload};
|
||||||
use crate::impl_type_option;
|
use crate::impl_type_option;
|
||||||
use crate::services::entities::{CellIdentifier, CellIdentifierPayload};
|
|
||||||
use crate::services::field::type_options::util::get_cell_data;
|
use crate::services::field::type_options::util::get_cell_data;
|
||||||
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
|
||||||
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData, TypeOptionCellData};
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
use crate::dart_notification::{send_dart_notification, GridNotification};
|
use crate::dart_notification::{send_dart_notification, GridNotification};
|
||||||
|
use crate::entities::CellIdentifier;
|
||||||
use crate::manager::GridUser;
|
use crate::manager::GridUser;
|
||||||
use crate::services::block_meta_manager::GridBlockMetaEditorManager;
|
use crate::services::block_meta_manager::GridBlockMetaEditorManager;
|
||||||
use crate::services::entities::CellIdentifier;
|
|
||||||
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
|
use crate::services::field::{default_type_option_builder_from_type, type_option_builder_from_bytes, FieldBuilder};
|
||||||
use crate::services::persistence::block_index::BlockIndexPersistence;
|
use crate::services::persistence::block_index::BlockIndexPersistence;
|
||||||
use crate::services::row::*;
|
use crate::services::row::*;
|
||||||
|
@ -2,7 +2,6 @@ mod util;
|
|||||||
|
|
||||||
pub mod block_meta_editor;
|
pub mod block_meta_editor;
|
||||||
mod block_meta_manager;
|
mod block_meta_manager;
|
||||||
pub mod entities;
|
|
||||||
pub mod field;
|
pub mod field;
|
||||||
pub mod grid_editor;
|
pub mod grid_editor;
|
||||||
pub mod persistence;
|
pub mod persistence;
|
||||||
|
Reference in New Issue
Block a user