mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: enable drag to expand field's width
This commit is contained in:
parent
4e3d2672ec
commit
ab896cbc8f
@ -24,13 +24,15 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
|||||||
_startListening();
|
_startListening();
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (field) {
|
didReceiveFieldUpdate: (field) {
|
||||||
emit(state.copyWith(field: field));
|
emit(state.copyWith(field: cellContext.field));
|
||||||
},
|
},
|
||||||
updateWidth: (offset) {
|
startUpdateWidth: (offset) {
|
||||||
final defaultWidth = state.field.width.toDouble();
|
final width = state.width + offset;
|
||||||
final width = defaultWidth + offset;
|
emit(state.copyWith(width: width));
|
||||||
if (width > defaultWidth && width < 300) {
|
},
|
||||||
_fieldService.updateField(width: width);
|
endUpdateWidth: () {
|
||||||
|
if (state.width != state.field.width.toDouble()) {
|
||||||
|
_fieldService.updateField(width: state.width);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -61,7 +63,8 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
|||||||
class FieldCellEvent with _$FieldCellEvent {
|
class FieldCellEvent with _$FieldCellEvent {
|
||||||
const factory FieldCellEvent.initial() = _InitialCell;
|
const factory FieldCellEvent.initial() = _InitialCell;
|
||||||
const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
|
const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
|
||||||
const factory FieldCellEvent.updateWidth(double offset) = _UpdateWidth;
|
const factory FieldCellEvent.startUpdateWidth(double offset) = _StartUpdateWidth;
|
||||||
|
const factory FieldCellEvent.endUpdateWidth() = _EndUpdateWidth;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -69,10 +72,12 @@ class FieldCellState with _$FieldCellState {
|
|||||||
const factory FieldCellState({
|
const factory FieldCellState({
|
||||||
required String gridId,
|
required String gridId,
|
||||||
required Field field,
|
required Field field,
|
||||||
|
required double width,
|
||||||
}) = _FieldCellState;
|
}) = _FieldCellState;
|
||||||
|
|
||||||
factory FieldCellState.initial(GridFieldCellContext cellContext) => FieldCellState(
|
factory FieldCellState.initial(GridFieldCellContext cellContext) => FieldCellState(
|
||||||
gridId: cellContext.gridId,
|
gridId: cellContext.gridId,
|
||||||
field: cellContext.field,
|
field: cellContext.field,
|
||||||
|
width: cellContext.field.width.toDouble(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
|||||||
_rowService.createRow();
|
_rowService.createRow();
|
||||||
},
|
},
|
||||||
didReceiveCellDatas: (_DidReceiveCellDatas value) async {
|
didReceiveCellDatas: (_DidReceiveCellDatas value) async {
|
||||||
final fields = value.gridCellMap.values.map((e) => CellSnapshot(e.field)).toList();
|
final fields = value.gridCellMap.values.map((e) => GridCellEquatable(e.field)).toList();
|
||||||
final snapshots = UnmodifiableListView(fields);
|
final snapshots = UnmodifiableListView(fields);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
gridCellMap: value.gridCellMap,
|
gridCellMap: value.gridCellMap,
|
||||||
@ -74,26 +74,27 @@ class RowState with _$RowState {
|
|||||||
const factory RowState({
|
const factory RowState({
|
||||||
required GridRow rowData,
|
required GridRow rowData,
|
||||||
required GridCellMap gridCellMap,
|
required GridCellMap gridCellMap,
|
||||||
required UnmodifiableListView<CellSnapshot> snapshots,
|
required UnmodifiableListView<GridCellEquatable> snapshots,
|
||||||
GridRowChangeReason? changeReason,
|
GridRowChangeReason? changeReason,
|
||||||
}) = _RowState;
|
}) = _RowState;
|
||||||
|
|
||||||
factory RowState.initial(GridRow rowData, GridCellMap cellDataMap) => RowState(
|
factory RowState.initial(GridRow rowData, GridCellMap cellDataMap) => RowState(
|
||||||
rowData: rowData,
|
rowData: rowData,
|
||||||
gridCellMap: cellDataMap,
|
gridCellMap: cellDataMap,
|
||||||
snapshots: UnmodifiableListView(cellDataMap.values.map((e) => CellSnapshot(e.field)).toList()),
|
snapshots: UnmodifiableListView(cellDataMap.values.map((e) => GridCellEquatable(e.field)).toList()),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CellSnapshot extends Equatable {
|
class GridCellEquatable extends Equatable {
|
||||||
final Field _field;
|
final Field _field;
|
||||||
|
|
||||||
const CellSnapshot(Field field) : _field = field;
|
const GridCellEquatable(Field field) : _field = field;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
_field.id,
|
_field.id,
|
||||||
_field.fieldType,
|
_field.fieldType,
|
||||||
_field.visibility,
|
_field.visibility,
|
||||||
|
_field.width,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import 'package:flowy_infra/theme.dart';
|
|||||||
import 'package:flowy_infra_ui/style_widget/button.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/hover.dart';
|
||||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||||
import 'package:flowy_sdk/log.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/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -24,6 +23,7 @@ class GridFieldCell extends StatelessWidget {
|
|||||||
return BlocProvider(
|
return BlocProvider(
|
||||||
create: (context) => FieldCellBloc(cellContext: cellContext)..add(const FieldCellEvent.initial()),
|
create: (context) => FieldCellBloc(cellContext: cellContext)..add(const FieldCellEvent.initial()),
|
||||||
child: BlocBuilder<FieldCellBloc, FieldCellState>(
|
child: BlocBuilder<FieldCellBloc, FieldCellState>(
|
||||||
|
// buildWhen: (p, c) => p.field != c.field,
|
||||||
builder: (context, state) {
|
builder: (context, state) {
|
||||||
final button = FieldCellButton(
|
final button = FieldCellButton(
|
||||||
field: state.field,
|
field: state.field,
|
||||||
@ -38,7 +38,7 @@ class GridFieldCell extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return _GridHeaderCellContainer(
|
return _GridHeaderCellContainer(
|
||||||
width: state.field.width.toDouble(),
|
width: state.width,
|
||||||
child: Stack(
|
child: Stack(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
@ -60,13 +60,14 @@ class GridFieldCell extends StatelessWidget {
|
|||||||
|
|
||||||
void _showFieldEditor(BuildContext context) {
|
void _showFieldEditor(BuildContext context) {
|
||||||
final state = context.read<FieldCellBloc>().state;
|
final state = context.read<FieldCellBloc>().state;
|
||||||
|
final field = state.field;
|
||||||
|
|
||||||
FieldEditor(
|
FieldEditor(
|
||||||
gridId: state.gridId,
|
gridId: state.gridId,
|
||||||
fieldName: state.field.name,
|
fieldName: field.name,
|
||||||
contextLoader: FieldContextLoader(
|
contextLoader: FieldContextLoader(
|
||||||
gridId: state.gridId,
|
gridId: state.gridId,
|
||||||
field: state.field,
|
field: field,
|
||||||
),
|
),
|
||||||
).show(context);
|
).show(context);
|
||||||
}
|
}
|
||||||
@ -113,19 +114,17 @@ class _DragToExpandLine extends StatelessWidget {
|
|||||||
onTap: () {},
|
onTap: () {},
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
behavior: HitTestBehavior.opaque,
|
behavior: HitTestBehavior.opaque,
|
||||||
onHorizontalDragCancel: () {},
|
|
||||||
onHorizontalDragUpdate: (value) {
|
onHorizontalDragUpdate: (value) {
|
||||||
// context.read<FieldCellBloc>().add(FieldCellEvent.updateWidth(value.delta.dx));
|
context.read<FieldCellBloc>().add(FieldCellEvent.startUpdateWidth(value.delta.dx));
|
||||||
Log.info(value);
|
|
||||||
},
|
},
|
||||||
onHorizontalDragEnd: (end) {
|
onHorizontalDragEnd: (end) {
|
||||||
Log.info(end);
|
context.read<FieldCellBloc>().add(const FieldCellEvent.endUpdateWidth());
|
||||||
},
|
},
|
||||||
child: FlowyHover(
|
child: FlowyHover(
|
||||||
style: HoverStyle(
|
style: HoverStyle(
|
||||||
hoverColor: theme.main1,
|
hoverColor: theme.main1,
|
||||||
borderRadius: BorderRadius.zero,
|
borderRadius: BorderRadius.zero,
|
||||||
contentMargin: const EdgeInsets.only(left: 5),
|
contentMargin: const EdgeInsets.only(left: 6),
|
||||||
),
|
),
|
||||||
child: const SizedBox(width: 2),
|
child: const SizedBox(width: 2),
|
||||||
),
|
),
|
||||||
|
@ -27,7 +27,7 @@ impl TypeOptionBuilder for RichTextTypeOptionBuilder {
|
|||||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
||||||
pub struct RichTextTypeOption {
|
pub struct RichTextTypeOption {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
data: String, //It's not used.
|
data: String, //It's not used yet
|
||||||
}
|
}
|
||||||
impl_type_option!(RichTextTypeOption, FieldType::RichText);
|
impl_type_option!(RichTextTypeOption, FieldType::RichText);
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ impl TypeOptionBuilder for URLTypeOptionBuilder {
|
|||||||
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
|
#[derive(Debug, Clone, Serialize, Deserialize, Default, ProtoBuf)]
|
||||||
pub struct URLTypeOption {
|
pub struct URLTypeOption {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
data: String, //It's not used.
|
data: String, //It's not used yet.
|
||||||
}
|
}
|
||||||
impl_type_option!(URLTypeOption, FieldType::URL);
|
impl_type_option!(URLTypeOption, FieldType::URL);
|
||||||
|
|
||||||
@ -56,31 +56,34 @@ impl CellDataOperation<EncodedCellData<URLCellData>, String> for URLTypeOption {
|
|||||||
C: Into<CellContentChangeset>,
|
C: Into<CellContentChangeset>,
|
||||||
{
|
{
|
||||||
let changeset = changeset.into();
|
let changeset = changeset.into();
|
||||||
let mut cell_data = URLCellData {
|
let mut url = "".to_string();
|
||||||
url: "".to_string(),
|
|
||||||
content: changeset.to_string(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if let Ok(Some(m)) = URL_REGEX.find(&changeset) {
|
if let Ok(Some(m)) = URL_REGEX.find(&changeset) {
|
||||||
|
url = auto_append_scheme(m.as_str());
|
||||||
|
}
|
||||||
|
URLCellData {
|
||||||
|
url,
|
||||||
|
content: changeset.to_string(),
|
||||||
|
}
|
||||||
|
.to_json()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn auto_append_scheme(s: &str) -> String {
|
||||||
// Only support https scheme by now
|
// Only support https scheme by now
|
||||||
match url::Url::parse(m.as_str()) {
|
match url::Url::parse(s) {
|
||||||
Ok(url) => {
|
Ok(url) => {
|
||||||
if url.scheme() == "https" {
|
if url.scheme() == "https" {
|
||||||
cell_data.url = url.into();
|
url.into()
|
||||||
} else {
|
} else {
|
||||||
cell_data.url = format!("https://{}", m.as_str());
|
format!("https://{}", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(_) => {
|
Err(_) => {
|
||||||
cell_data.url = format!("https://{}", m.as_str());
|
format!("https://{}", s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_data.to_json()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
|
#[derive(Clone, Debug, Default, Serialize, Deserialize, ProtoBuf)]
|
||||||
pub struct URLCellData {
|
pub struct URLCellData {
|
||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
|
Loading…
Reference in New Issue
Block a user