mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: grid block meta editor
This commit is contained in:
parent
9a791974b4
commit
e11176436d
@ -17,7 +17,7 @@ class GridMeta extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridMeta', createEmptyInstance: create)
|
||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'gridId')
|
||||
..pc<Field>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fields', $pb.PbFieldType.PM, subBuilder: Field.create)
|
||||
..pc<Block>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blocks', $pb.PbFieldType.PM, subBuilder: Block.create)
|
||||
..pc<GridBlock>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blocks', $pb.PbFieldType.PM, subBuilder: GridBlock.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@ -25,7 +25,7 @@ class GridMeta extends $pb.GeneratedMessage {
|
||||
factory GridMeta({
|
||||
$core.String? gridId,
|
||||
$core.Iterable<Field>? fields,
|
||||
$core.Iterable<Block>? blocks,
|
||||
$core.Iterable<GridBlock>? blocks,
|
||||
}) {
|
||||
final _result = create();
|
||||
if (gridId != null) {
|
||||
@ -73,19 +73,19 @@ class GridMeta extends $pb.GeneratedMessage {
|
||||
$core.List<Field> get fields => $_getList(1);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.List<Block> get blocks => $_getList(2);
|
||||
$core.List<GridBlock> get blocks => $_getList(2);
|
||||
}
|
||||
|
||||
class Block extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'Block', createEmptyInstance: create)
|
||||
class GridBlock extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlock', createEmptyInstance: create)
|
||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'id')
|
||||
..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'startRowIndex', $pb.PbFieldType.O3)
|
||||
..a<$core.int>(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rowCount', $pb.PbFieldType.O3)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
Block._() : super();
|
||||
factory Block({
|
||||
GridBlock._() : super();
|
||||
factory GridBlock({
|
||||
$core.String? id,
|
||||
$core.int? startRowIndex,
|
||||
$core.int? rowCount,
|
||||
@ -102,26 +102,26 @@ class Block extends $pb.GeneratedMessage {
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
factory Block.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Block.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
factory GridBlock.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory GridBlock.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Block clone() => Block()..mergeFromMessage(this);
|
||||
GridBlock clone() => GridBlock()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Block copyWith(void Function(Block) updates) => super.copyWith((message) => updates(message as Block)) as Block; // ignore: deprecated_member_use
|
||||
GridBlock copyWith(void Function(GridBlock) updates) => super.copyWith((message) => updates(message as GridBlock)) as GridBlock; // ignore: deprecated_member_use
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Block create() => Block._();
|
||||
Block createEmptyInstance() => create();
|
||||
static $pb.PbList<Block> createRepeated() => $pb.PbList<Block>();
|
||||
static GridBlock create() => GridBlock._();
|
||||
GridBlock createEmptyInstance() => create();
|
||||
static $pb.PbList<GridBlock> createRepeated() => $pb.PbList<GridBlock>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Block getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Block>(create);
|
||||
static Block? _defaultInstance;
|
||||
static GridBlock getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridBlock>(create);
|
||||
static GridBlock? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get id => $_getSZ(0);
|
||||
@ -151,15 +151,15 @@ class Block extends $pb.GeneratedMessage {
|
||||
void clearRowCount() => clearField(3);
|
||||
}
|
||||
|
||||
class BlockMeta extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'BlockMeta', createEmptyInstance: create)
|
||||
class GridBlockMeta extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'GridBlockMeta', createEmptyInstance: create)
|
||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'blockId')
|
||||
..pc<RowMeta>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'rows', $pb.PbFieldType.PM, subBuilder: RowMeta.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
BlockMeta._() : super();
|
||||
factory BlockMeta({
|
||||
GridBlockMeta._() : super();
|
||||
factory GridBlockMeta({
|
||||
$core.String? blockId,
|
||||
$core.Iterable<RowMeta>? rows,
|
||||
}) {
|
||||
@ -172,26 +172,26 @@ class BlockMeta extends $pb.GeneratedMessage {
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
factory BlockMeta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory BlockMeta.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
factory GridBlockMeta.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory GridBlockMeta.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
BlockMeta clone() => BlockMeta()..mergeFromMessage(this);
|
||||
GridBlockMeta clone() => GridBlockMeta()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
BlockMeta copyWith(void Function(BlockMeta) updates) => super.copyWith((message) => updates(message as BlockMeta)) as BlockMeta; // ignore: deprecated_member_use
|
||||
GridBlockMeta copyWith(void Function(GridBlockMeta) updates) => super.copyWith((message) => updates(message as GridBlockMeta)) as GridBlockMeta; // ignore: deprecated_member_use
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BlockMeta create() => BlockMeta._();
|
||||
BlockMeta createEmptyInstance() => create();
|
||||
static $pb.PbList<BlockMeta> createRepeated() => $pb.PbList<BlockMeta>();
|
||||
static GridBlockMeta create() => GridBlockMeta._();
|
||||
GridBlockMeta createEmptyInstance() => create();
|
||||
static $pb.PbList<GridBlockMeta> createRepeated() => $pb.PbList<GridBlockMeta>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static BlockMeta getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<BlockMeta>(create);
|
||||
static BlockMeta? _defaultInstance;
|
||||
static GridBlockMeta getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<GridBlockMeta>(create);
|
||||
static GridBlockMeta? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get blockId => $_getSZ(0);
|
||||
@ -394,6 +394,244 @@ class RepeatedField extends $pb.GeneratedMessage {
|
||||
$core.List<Field> get items => $_getList(0);
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfName {
|
||||
name,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfDesc {
|
||||
desc,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfFieldType {
|
||||
fieldType,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfFrozen {
|
||||
frozen,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfVisibility {
|
||||
visibility,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfWidth {
|
||||
width,
|
||||
notSet
|
||||
}
|
||||
|
||||
enum FieldChangeset_OneOfTypeOptions {
|
||||
typeOptions,
|
||||
notSet
|
||||
}
|
||||
|
||||
class FieldChangeset extends $pb.GeneratedMessage {
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfName> _FieldChangeset_OneOfNameByTag = {
|
||||
2 : FieldChangeset_OneOfName.name,
|
||||
0 : FieldChangeset_OneOfName.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfDesc> _FieldChangeset_OneOfDescByTag = {
|
||||
3 : FieldChangeset_OneOfDesc.desc,
|
||||
0 : FieldChangeset_OneOfDesc.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfFieldType> _FieldChangeset_OneOfFieldTypeByTag = {
|
||||
4 : FieldChangeset_OneOfFieldType.fieldType,
|
||||
0 : FieldChangeset_OneOfFieldType.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfFrozen> _FieldChangeset_OneOfFrozenByTag = {
|
||||
5 : FieldChangeset_OneOfFrozen.frozen,
|
||||
0 : FieldChangeset_OneOfFrozen.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfVisibility> _FieldChangeset_OneOfVisibilityByTag = {
|
||||
6 : FieldChangeset_OneOfVisibility.visibility,
|
||||
0 : FieldChangeset_OneOfVisibility.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfWidth> _FieldChangeset_OneOfWidthByTag = {
|
||||
7 : FieldChangeset_OneOfWidth.width,
|
||||
0 : FieldChangeset_OneOfWidth.notSet
|
||||
};
|
||||
static const $core.Map<$core.int, FieldChangeset_OneOfTypeOptions> _FieldChangeset_OneOfTypeOptionsByTag = {
|
||||
8 : FieldChangeset_OneOfTypeOptions.typeOptions,
|
||||
0 : FieldChangeset_OneOfTypeOptions.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'FieldChangeset', createEmptyInstance: create)
|
||||
..oo(0, [2])
|
||||
..oo(1, [3])
|
||||
..oo(2, [4])
|
||||
..oo(3, [5])
|
||||
..oo(4, [6])
|
||||
..oo(5, [7])
|
||||
..oo(6, [8])
|
||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldId')
|
||||
..aOS(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'name')
|
||||
..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'desc')
|
||||
..e<FieldType>(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'fieldType', $pb.PbFieldType.OE, defaultOrMaker: FieldType.RichText, valueOf: FieldType.valueOf, enumValues: FieldType.values)
|
||||
..aOB(5, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'frozen')
|
||||
..aOB(6, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'visibility')
|
||||
..a<$core.int>(7, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'width', $pb.PbFieldType.O3)
|
||||
..aOM<AnyData>(8, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeOptions', subBuilder: AnyData.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
FieldChangeset._() : super();
|
||||
factory FieldChangeset({
|
||||
$core.String? fieldId,
|
||||
$core.String? name,
|
||||
$core.String? desc,
|
||||
FieldType? fieldType,
|
||||
$core.bool? frozen,
|
||||
$core.bool? visibility,
|
||||
$core.int? width,
|
||||
AnyData? typeOptions,
|
||||
}) {
|
||||
final _result = create();
|
||||
if (fieldId != null) {
|
||||
_result.fieldId = fieldId;
|
||||
}
|
||||
if (name != null) {
|
||||
_result.name = name;
|
||||
}
|
||||
if (desc != null) {
|
||||
_result.desc = desc;
|
||||
}
|
||||
if (fieldType != null) {
|
||||
_result.fieldType = fieldType;
|
||||
}
|
||||
if (frozen != null) {
|
||||
_result.frozen = frozen;
|
||||
}
|
||||
if (visibility != null) {
|
||||
_result.visibility = visibility;
|
||||
}
|
||||
if (width != null) {
|
||||
_result.width = width;
|
||||
}
|
||||
if (typeOptions != null) {
|
||||
_result.typeOptions = typeOptions;
|
||||
}
|
||||
return _result;
|
||||
}
|
||||
factory FieldChangeset.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory FieldChangeset.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
FieldChangeset clone() => FieldChangeset()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
FieldChangeset copyWith(void Function(FieldChangeset) updates) => super.copyWith((message) => updates(message as FieldChangeset)) as FieldChangeset; // ignore: deprecated_member_use
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FieldChangeset create() => FieldChangeset._();
|
||||
FieldChangeset createEmptyInstance() => create();
|
||||
static $pb.PbList<FieldChangeset> createRepeated() => $pb.PbList<FieldChangeset>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static FieldChangeset getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<FieldChangeset>(create);
|
||||
static FieldChangeset? _defaultInstance;
|
||||
|
||||
FieldChangeset_OneOfName whichOneOfName() => _FieldChangeset_OneOfNameByTag[$_whichOneof(0)]!;
|
||||
void clearOneOfName() => clearField($_whichOneof(0));
|
||||
|
||||
FieldChangeset_OneOfDesc whichOneOfDesc() => _FieldChangeset_OneOfDescByTag[$_whichOneof(1)]!;
|
||||
void clearOneOfDesc() => clearField($_whichOneof(1));
|
||||
|
||||
FieldChangeset_OneOfFieldType whichOneOfFieldType() => _FieldChangeset_OneOfFieldTypeByTag[$_whichOneof(2)]!;
|
||||
void clearOneOfFieldType() => clearField($_whichOneof(2));
|
||||
|
||||
FieldChangeset_OneOfFrozen whichOneOfFrozen() => _FieldChangeset_OneOfFrozenByTag[$_whichOneof(3)]!;
|
||||
void clearOneOfFrozen() => clearField($_whichOneof(3));
|
||||
|
||||
FieldChangeset_OneOfVisibility whichOneOfVisibility() => _FieldChangeset_OneOfVisibilityByTag[$_whichOneof(4)]!;
|
||||
void clearOneOfVisibility() => clearField($_whichOneof(4));
|
||||
|
||||
FieldChangeset_OneOfWidth whichOneOfWidth() => _FieldChangeset_OneOfWidthByTag[$_whichOneof(5)]!;
|
||||
void clearOneOfWidth() => clearField($_whichOneof(5));
|
||||
|
||||
FieldChangeset_OneOfTypeOptions whichOneOfTypeOptions() => _FieldChangeset_OneOfTypeOptionsByTag[$_whichOneof(6)]!;
|
||||
void clearOneOfTypeOptions() => clearField($_whichOneof(6));
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.String get fieldId => $_getSZ(0);
|
||||
@$pb.TagNumber(1)
|
||||
set fieldId($core.String v) { $_setString(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasFieldId() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearFieldId() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.String get name => $_getSZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set name($core.String v) { $_setString(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasName() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearName() => clearField(2);
|
||||
|
||||
@$pb.TagNumber(3)
|
||||
$core.String get desc => $_getSZ(2);
|
||||
@$pb.TagNumber(3)
|
||||
set desc($core.String v) { $_setString(2, v); }
|
||||
@$pb.TagNumber(3)
|
||||
$core.bool hasDesc() => $_has(2);
|
||||
@$pb.TagNumber(3)
|
||||
void clearDesc() => clearField(3);
|
||||
|
||||
@$pb.TagNumber(4)
|
||||
FieldType get fieldType => $_getN(3);
|
||||
@$pb.TagNumber(4)
|
||||
set fieldType(FieldType v) { setField(4, v); }
|
||||
@$pb.TagNumber(4)
|
||||
$core.bool hasFieldType() => $_has(3);
|
||||
@$pb.TagNumber(4)
|
||||
void clearFieldType() => clearField(4);
|
||||
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool get frozen => $_getBF(4);
|
||||
@$pb.TagNumber(5)
|
||||
set frozen($core.bool v) { $_setBool(4, v); }
|
||||
@$pb.TagNumber(5)
|
||||
$core.bool hasFrozen() => $_has(4);
|
||||
@$pb.TagNumber(5)
|
||||
void clearFrozen() => clearField(5);
|
||||
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool get visibility => $_getBF(5);
|
||||
@$pb.TagNumber(6)
|
||||
set visibility($core.bool v) { $_setBool(5, v); }
|
||||
@$pb.TagNumber(6)
|
||||
$core.bool hasVisibility() => $_has(5);
|
||||
@$pb.TagNumber(6)
|
||||
void clearVisibility() => clearField(6);
|
||||
|
||||
@$pb.TagNumber(7)
|
||||
$core.int get width => $_getIZ(6);
|
||||
@$pb.TagNumber(7)
|
||||
set width($core.int v) { $_setSignedInt32(6, v); }
|
||||
@$pb.TagNumber(7)
|
||||
$core.bool hasWidth() => $_has(6);
|
||||
@$pb.TagNumber(7)
|
||||
void clearWidth() => clearField(7);
|
||||
|
||||
@$pb.TagNumber(8)
|
||||
AnyData get typeOptions => $_getN(7);
|
||||
@$pb.TagNumber(8)
|
||||
set typeOptions(AnyData v) { setField(8, v); }
|
||||
@$pb.TagNumber(8)
|
||||
$core.bool hasTypeOptions() => $_has(7);
|
||||
@$pb.TagNumber(8)
|
||||
void clearTypeOptions() => clearField(8);
|
||||
@$pb.TagNumber(8)
|
||||
AnyData ensureTypeOptions() => $_ensure(7);
|
||||
}
|
||||
|
||||
class AnyData extends $pb.GeneratedMessage {
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'AnyData', createEmptyInstance: create)
|
||||
..aOS(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'typeId')
|
||||
|
@ -29,15 +29,15 @@ const GridMeta$json = const {
|
||||
'2': const [
|
||||
const {'1': 'grid_id', '3': 1, '4': 1, '5': 9, '10': 'gridId'},
|
||||
const {'1': 'fields', '3': 2, '4': 3, '5': 11, '6': '.Field', '10': 'fields'},
|
||||
const {'1': 'blocks', '3': 3, '4': 3, '5': 11, '6': '.Block', '10': 'blocks'},
|
||||
const {'1': 'blocks', '3': 3, '4': 3, '5': 11, '6': '.GridBlock', '10': 'blocks'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `GridMeta`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSHgoGZmllbGRzGAIgAygLMgYuRmllbGRSBmZpZWxkcxIeCgZibG9ja3MYAyADKAsyBi5CbG9ja1IGYmxvY2tz');
|
||||
@$core.Deprecated('Use blockDescriptor instead')
|
||||
const Block$json = const {
|
||||
'1': 'Block',
|
||||
final $typed_data.Uint8List gridMetaDescriptor = $convert.base64Decode('CghHcmlkTWV0YRIXCgdncmlkX2lkGAEgASgJUgZncmlkSWQSHgoGZmllbGRzGAIgAygLMgYuRmllbGRSBmZpZWxkcxIiCgZibG9ja3MYAyADKAsyCi5HcmlkQmxvY2tSBmJsb2Nrcw==');
|
||||
@$core.Deprecated('Use gridBlockDescriptor instead')
|
||||
const GridBlock$json = const {
|
||||
'1': 'GridBlock',
|
||||
'2': const [
|
||||
const {'1': 'id', '3': 1, '4': 1, '5': 9, '10': 'id'},
|
||||
const {'1': 'start_row_index', '3': 2, '4': 1, '5': 5, '10': 'startRowIndex'},
|
||||
@ -45,19 +45,19 @@ const Block$json = const {
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `Block`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List blockDescriptor = $convert.base64Decode('CgVCbG9jaxIOCgJpZBgBIAEoCVICaWQSJgoPc3RhcnRfcm93X2luZGV4GAIgASgFUg1zdGFydFJvd0luZGV4EhsKCXJvd19jb3VudBgDIAEoBVIIcm93Q291bnQ=');
|
||||
@$core.Deprecated('Use blockMetaDescriptor instead')
|
||||
const BlockMeta$json = const {
|
||||
'1': 'BlockMeta',
|
||||
/// Descriptor for `GridBlock`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List gridBlockDescriptor = $convert.base64Decode('CglHcmlkQmxvY2sSDgoCaWQYASABKAlSAmlkEiYKD3N0YXJ0X3Jvd19pbmRleBgCIAEoBVINc3RhcnRSb3dJbmRleBIbCglyb3dfY291bnQYAyABKAVSCHJvd0NvdW50');
|
||||
@$core.Deprecated('Use gridBlockMetaDescriptor instead')
|
||||
const GridBlockMeta$json = const {
|
||||
'1': 'GridBlockMeta',
|
||||
'2': const [
|
||||
const {'1': 'block_id', '3': 1, '4': 1, '5': 9, '10': 'blockId'},
|
||||
const {'1': 'rows', '3': 2, '4': 3, '5': 11, '6': '.RowMeta', '10': 'rows'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `BlockMeta`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List blockMetaDescriptor = $convert.base64Decode('CglCbG9ja01ldGESGQoIYmxvY2tfaWQYASABKAlSB2Jsb2NrSWQSHAoEcm93cxgCIAMoCzIILlJvd01ldGFSBHJvd3M=');
|
||||
/// Descriptor for `GridBlockMeta`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List gridBlockMetaDescriptor = $convert.base64Decode('Cg1HcmlkQmxvY2tNZXRhEhkKCGJsb2NrX2lkGAEgASgJUgdibG9ja0lkEhwKBHJvd3MYAiADKAsyCC5Sb3dNZXRhUgRyb3dz');
|
||||
@$core.Deprecated('Use fieldDescriptor instead')
|
||||
const Field$json = const {
|
||||
'1': 'Field',
|
||||
@ -85,6 +85,32 @@ const RepeatedField$json = const {
|
||||
|
||||
/// Descriptor for `RepeatedField`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List repeatedFieldDescriptor = $convert.base64Decode('Cg1SZXBlYXRlZEZpZWxkEhwKBWl0ZW1zGAEgAygLMgYuRmllbGRSBWl0ZW1z');
|
||||
@$core.Deprecated('Use fieldChangesetDescriptor instead')
|
||||
const FieldChangeset$json = const {
|
||||
'1': 'FieldChangeset',
|
||||
'2': const [
|
||||
const {'1': 'field_id', '3': 1, '4': 1, '5': 9, '10': 'fieldId'},
|
||||
const {'1': 'name', '3': 2, '4': 1, '5': 9, '9': 0, '10': 'name'},
|
||||
const {'1': 'desc', '3': 3, '4': 1, '5': 9, '9': 1, '10': 'desc'},
|
||||
const {'1': 'field_type', '3': 4, '4': 1, '5': 14, '6': '.FieldType', '9': 2, '10': 'fieldType'},
|
||||
const {'1': 'frozen', '3': 5, '4': 1, '5': 8, '9': 3, '10': 'frozen'},
|
||||
const {'1': 'visibility', '3': 6, '4': 1, '5': 8, '9': 4, '10': 'visibility'},
|
||||
const {'1': 'width', '3': 7, '4': 1, '5': 5, '9': 5, '10': 'width'},
|
||||
const {'1': 'type_options', '3': 8, '4': 1, '5': 11, '6': '.AnyData', '9': 6, '10': 'typeOptions'},
|
||||
],
|
||||
'8': const [
|
||||
const {'1': 'one_of_name'},
|
||||
const {'1': 'one_of_desc'},
|
||||
const {'1': 'one_of_field_type'},
|
||||
const {'1': 'one_of_frozen'},
|
||||
const {'1': 'one_of_visibility'},
|
||||
const {'1': 'one_of_width'},
|
||||
const {'1': 'one_of_type_options'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `FieldChangeset`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List fieldChangesetDescriptor = $convert.base64Decode('Cg5GaWVsZENoYW5nZXNldBIZCghmaWVsZF9pZBgBIAEoCVIHZmllbGRJZBIUCgRuYW1lGAIgASgJSABSBG5hbWUSFAoEZGVzYxgDIAEoCUgBUgRkZXNjEisKCmZpZWxkX3R5cGUYBCABKA4yCi5GaWVsZFR5cGVIAlIJZmllbGRUeXBlEhgKBmZyb3plbhgFIAEoCEgDUgZmcm96ZW4SIAoKdmlzaWJpbGl0eRgGIAEoCEgEUgp2aXNpYmlsaXR5EhYKBXdpZHRoGAcgASgFSAVSBXdpZHRoEi0KDHR5cGVfb3B0aW9ucxgIIAEoCzIILkFueURhdGFIBlILdHlwZU9wdGlvbnNCDQoLb25lX29mX25hbWVCDQoLb25lX29mX2Rlc2NCEwoRb25lX29mX2ZpZWxkX3R5cGVCDwoNb25lX29mX2Zyb3plbkITChFvbmVfb2ZfdmlzaWJpbGl0eUIOCgxvbmVfb2Zfd2lkdGhCFQoTb25lX29mX3R5cGVfb3B0aW9ucw==');
|
||||
@$core.Deprecated('Use anyDataDescriptor instead')
|
||||
const AnyData$json = const {
|
||||
'1': 'AnyData',
|
||||
|
@ -7,8 +7,8 @@ edition = "2018"
|
||||
[lib]
|
||||
name = "dart_ffi"
|
||||
# this value will change depending on the target os
|
||||
# default staticlib
|
||||
crate-type = ["staticlib"]
|
||||
# default cdylib
|
||||
crate-type = ["cdylib"]
|
||||
|
||||
|
||||
[dependencies]
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::queue::BlockRevisionCompact;
|
||||
use crate::queue::TextBlockRevisionCompactor;
|
||||
use crate::web_socket::{make_block_ws_manager, EditorCommandSender};
|
||||
use crate::{
|
||||
errors::FlowyError,
|
||||
@ -40,9 +40,7 @@ impl ClientTextBlockEditor {
|
||||
rev_web_socket: Arc<dyn RevisionWebSocket>,
|
||||
cloud_service: Arc<dyn RevisionCloudService>,
|
||||
) -> FlowyResult<Arc<Self>> {
|
||||
let document_info = rev_manager
|
||||
.load::<BlockInfoBuilder, BlockRevisionCompact>(cloud_service)
|
||||
.await?;
|
||||
let document_info = rev_manager.load::<BlockInfoBuilder>(cloud_service).await?;
|
||||
let delta = document_info.delta()?;
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let doc_id = doc_id.to_string();
|
||||
|
@ -8,6 +8,7 @@ use flowy_collaboration::entities::{
|
||||
};
|
||||
use flowy_database::ConnectionPool;
|
||||
use flowy_error::FlowyResult;
|
||||
use flowy_sync::disk::SQLiteTextBlockRevisionPersistence;
|
||||
use flowy_sync::{RevisionCloudService, RevisionManager, RevisionPersistence, RevisionWebSocket};
|
||||
use lib_infra::future::FutureResult;
|
||||
use std::{convert::TryInto, sync::Arc};
|
||||
@ -84,7 +85,7 @@ impl TextBlockManager {
|
||||
let doc_id = doc_id.as_ref().to_owned();
|
||||
let db_pool = self.user.db_pool()?;
|
||||
// Maybe we could save the block to disk without creating the RevisionManager
|
||||
let rev_manager = self.make_block_rev_manager(&doc_id, db_pool)?;
|
||||
let rev_manager = self.make_rev_manager(&doc_id, db_pool)?;
|
||||
let _ = rev_manager.reset_object(revisions).await?;
|
||||
Ok(())
|
||||
}
|
||||
@ -111,20 +112,20 @@ impl TextBlockManager {
|
||||
match self.editor_map.get(block_id) {
|
||||
None => {
|
||||
let db_pool = self.user.db_pool()?;
|
||||
self.make_block_editor(block_id, db_pool).await
|
||||
self.make_text_block_editor(block_id, db_pool).await
|
||||
}
|
||||
Some(editor) => Ok(editor),
|
||||
}
|
||||
}
|
||||
|
||||
async fn make_block_editor(
|
||||
async fn make_text_block_editor(
|
||||
&self,
|
||||
block_id: &str,
|
||||
pool: Arc<ConnectionPool>,
|
||||
) -> Result<Arc<ClientTextBlockEditor>, FlowyError> {
|
||||
let user = self.user.clone();
|
||||
let token = self.user.token()?;
|
||||
let rev_manager = self.make_block_rev_manager(block_id, pool.clone())?;
|
||||
let rev_manager = self.make_rev_manager(block_id, pool.clone())?;
|
||||
let cloud_service = Arc::new(TextBlockRevisionCloudService {
|
||||
token,
|
||||
server: self.cloud_service.clone(),
|
||||
@ -135,9 +136,10 @@ impl TextBlockManager {
|
||||
Ok(doc_editor)
|
||||
}
|
||||
|
||||
fn make_block_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, FlowyError> {
|
||||
fn make_rev_manager(&self, doc_id: &str, pool: Arc<ConnectionPool>) -> Result<RevisionManager, FlowyError> {
|
||||
let user_id = self.user.user_id()?;
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, doc_id, pool));
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(&user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, doc_id, disk_cache));
|
||||
Ok(RevisionManager::new(&user_id, doc_id, rev_persistence))
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
use crate::web_socket::EditorCommandReceiver;
|
||||
use crate::TextBlockUser;
|
||||
use async_stream::stream;
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::util::make_delta_from_revisions;
|
||||
use flowy_collaboration::{
|
||||
client_document::{history::UndoResult, ClientDocument},
|
||||
@ -8,8 +9,9 @@ use flowy_collaboration::{
|
||||
errors::CollaborateError,
|
||||
};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sync::{DeltaMD5, RevisionCompact, RevisionManager, RichTextTransformDeltas, TransformDeltas};
|
||||
use flowy_sync::{DeltaMD5, RevisionCompactor, RevisionManager, RichTextTransformDeltas, TransformDeltas};
|
||||
use futures::stream::StreamExt;
|
||||
use lib_ot::core::{Attributes, Delta};
|
||||
use lib_ot::{
|
||||
core::{Interval, OperationTransformable},
|
||||
rich_text::{RichTextAttribute, RichTextAttributes, RichTextDelta},
|
||||
@ -187,31 +189,17 @@ impl EditBlockQueue {
|
||||
);
|
||||
let _ = self
|
||||
.rev_manager
|
||||
.add_local_revision::<BlockRevisionCompact>(&revision)
|
||||
.add_local_revision(&revision, Box::new(TextBlockRevisionCompactor()))
|
||||
.await?;
|
||||
Ok(rev_id.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct BlockRevisionCompact();
|
||||
impl RevisionCompact for BlockRevisionCompact {
|
||||
fn compact_revisions(user_id: &str, object_id: &str, mut revisions: Vec<Revision>) -> FlowyResult<Revision> {
|
||||
if revisions.is_empty() {
|
||||
return Err(FlowyError::internal().context("Can't compact the empty block's revisions"));
|
||||
}
|
||||
|
||||
if revisions.len() == 1 {
|
||||
return Ok(revisions.pop().unwrap());
|
||||
}
|
||||
|
||||
let first_revision = revisions.first().unwrap();
|
||||
let last_revision = revisions.last().unwrap();
|
||||
|
||||
let (base_rev_id, rev_id) = first_revision.pair_rev_id();
|
||||
let md5 = last_revision.md5.clone();
|
||||
pub(crate) struct TextBlockRevisionCompactor();
|
||||
impl RevisionCompactor for TextBlockRevisionCompactor {
|
||||
fn bytes_from_revisions(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes> {
|
||||
let delta = make_delta_from_revisions::<RichTextAttributes>(revisions)?;
|
||||
let delta_data = delta.to_bytes();
|
||||
Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5))
|
||||
Ok(delta.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,2 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE kv_table;
|
||||
DROP TABLE grid_rev_table;
|
||||
DROP TABLE kv_table;
|
@ -2,13 +2,4 @@
|
||||
CREATE TABLE kv_table (
|
||||
key TEXT NOT NULL PRIMARY KEY,
|
||||
value BLOB NOT NULL DEFAULT (x'')
|
||||
);
|
||||
|
||||
CREATE TABLE grid_rev_table (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
object_id TEXT NOT NULL DEFAULT '',
|
||||
base_rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
data BLOB NOT NULL DEFAULT (x''),
|
||||
state INTEGER NOT NULL DEFAULT 0
|
||||
);
|
@ -0,0 +1,3 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE grid_rev_table;
|
||||
DROP TABLE grid_meta_rev_table;
|
@ -0,0 +1,18 @@
|
||||
-- Your SQL goes here
|
||||
CREATE TABLE grid_rev_table (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
object_id TEXT NOT NULL DEFAULT '',
|
||||
base_rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
data BLOB NOT NULL DEFAULT (x''),
|
||||
state INTEGER NOT NULL DEFAULT 0
|
||||
);
|
||||
|
||||
CREATE TABLE grid_meta_rev_table (
|
||||
id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
|
||||
object_id TEXT NOT NULL DEFAULT '',
|
||||
base_rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
rev_id BIGINT NOT NULL DEFAULT 0,
|
||||
data BLOB NOT NULL DEFAULT (x''),
|
||||
state INTEGER NOT NULL DEFAULT 0
|
||||
);
|
@ -160,3 +160,39 @@ macro_rules! impl_sql_integer_expression {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! impl_rev_state_map {
|
||||
($target:ident) => {
|
||||
impl std::convert::From<i32> for $target {
|
||||
fn from(value: i32) -> Self {
|
||||
match value {
|
||||
0 => $target::Sync,
|
||||
1 => $target::Ack,
|
||||
o => {
|
||||
tracing::error!("Unsupported rev state {}, fallback to RevState::Local", o);
|
||||
$target::Sync
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<$target> for RevisionState {
|
||||
fn from(s: $target) -> Self {
|
||||
match s {
|
||||
$target::Sync => RevisionState::Sync,
|
||||
$target::Ack => RevisionState::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<RevisionState> for $target {
|
||||
fn from(s: RevisionState) -> Self {
|
||||
match s {
|
||||
RevisionState::Sync => $target::Sync,
|
||||
RevisionState::Ack => $target::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
@ -21,6 +21,17 @@ table! {
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
grid_meta_rev_table (id) {
|
||||
id -> Integer,
|
||||
object_id -> Text,
|
||||
base_rev_id -> BigInt,
|
||||
rev_id -> BigInt,
|
||||
data -> Binary,
|
||||
state -> Integer,
|
||||
}
|
||||
}
|
||||
|
||||
table! {
|
||||
grid_rev_table (id) {
|
||||
id -> Integer,
|
||||
@ -102,6 +113,7 @@ table! {
|
||||
allow_tables_to_appear_in_same_query!(
|
||||
app_table,
|
||||
doc_table,
|
||||
grid_meta_rev_table,
|
||||
grid_rev_table,
|
||||
kv_table,
|
||||
rev_table,
|
||||
|
@ -17,7 +17,8 @@ use flowy_collaboration::{client_folder::FolderPad, entities::ws_data::ServerRev
|
||||
use flowy_error::FlowyError;
|
||||
use flowy_folder_data_model::entities::view::ViewDataType;
|
||||
use flowy_folder_data_model::user_default;
|
||||
use flowy_sync::RevisionWebSocket;
|
||||
use flowy_sync::disk::SQLiteTextBlockRevisionPersistence;
|
||||
use flowy_sync::{RevisionManager, RevisionPersistence, RevisionWebSocket};
|
||||
use lazy_static::lazy_static;
|
||||
use lib_infra::future::FutureResult;
|
||||
use std::{collections::HashMap, convert::TryInto, fmt::Formatter, sync::Arc};
|
||||
@ -163,7 +164,12 @@ impl FolderManager {
|
||||
let _ = self.persistence.initialize(user_id, &folder_id).await?;
|
||||
|
||||
let pool = self.persistence.db_pool()?;
|
||||
let folder_editor = ClientFolderEditor::new(user_id, &folder_id, token, pool, self.web_socket.clone()).await?;
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(&user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), disk_cache));
|
||||
let rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), rev_persistence);
|
||||
|
||||
let folder_editor =
|
||||
ClientFolderEditor::new(user_id, &folder_id, token, rev_manager, self.web_socket.clone()).await?;
|
||||
*self.folder_editor.write().await = Some(Arc::new(folder_editor));
|
||||
|
||||
let _ = self.app_controller.initialize()?;
|
||||
|
@ -5,14 +5,16 @@ use flowy_collaboration::{
|
||||
};
|
||||
|
||||
use crate::manager::FolderId;
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::util::make_delta_from_revisions;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_sync::disk::RevisionDiskCache;
|
||||
use flowy_sync::{
|
||||
RevisionCloudService, RevisionCompact, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
|
||||
RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder, RevisionPersistence,
|
||||
RevisionWebSocket, RevisionWebSocketManager,
|
||||
};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
use lib_ot::core::{Delta, PlainTextAttributes};
|
||||
use lib_sqlite::ConnectionPool;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
@ -30,19 +32,13 @@ impl ClientFolderEditor {
|
||||
user_id: &str,
|
||||
folder_id: &FolderId,
|
||||
token: &str,
|
||||
pool: Arc<ConnectionPool>,
|
||||
mut rev_manager: RevisionManager,
|
||||
web_socket: Arc<dyn RevisionWebSocket>,
|
||||
) -> FlowyResult<Self> {
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), pool));
|
||||
let mut rev_manager = RevisionManager::new(user_id, folder_id.as_ref(), rev_persistence);
|
||||
let cloud = Arc::new(FolderRevisionCloudService {
|
||||
token: token.to_string(),
|
||||
});
|
||||
let folder = Arc::new(RwLock::new(
|
||||
rev_manager
|
||||
.load::<FolderPadBuilder, FolderRevisionCompact>(cloud)
|
||||
.await?,
|
||||
));
|
||||
let folder = Arc::new(RwLock::new(rev_manager.load::<FolderPadBuilder>(cloud).await?));
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let ws_manager = make_folder_ws_manager(
|
||||
user_id,
|
||||
@ -86,7 +82,7 @@ impl ClientFolderEditor {
|
||||
);
|
||||
let _ = futures::executor::block_on(async {
|
||||
self.rev_manager
|
||||
.add_local_revision::<FolderRevisionCompact>(&revision)
|
||||
.add_local_revision(&revision, Box::new(FolderRevisionCompactor()))
|
||||
.await
|
||||
})?;
|
||||
Ok(())
|
||||
@ -128,24 +124,10 @@ impl ClientFolderEditor {
|
||||
}
|
||||
}
|
||||
|
||||
struct FolderRevisionCompact();
|
||||
impl RevisionCompact for FolderRevisionCompact {
|
||||
fn compact_revisions(user_id: &str, object_id: &str, mut revisions: Vec<Revision>) -> FlowyResult<Revision> {
|
||||
if revisions.is_empty() {
|
||||
return Err(FlowyError::internal().context("Can't compact the empty folder's revisions"));
|
||||
}
|
||||
|
||||
if revisions.len() == 1 {
|
||||
return Ok(revisions.pop().unwrap());
|
||||
}
|
||||
|
||||
let first_revision = revisions.first().unwrap();
|
||||
let last_revision = revisions.last().unwrap();
|
||||
|
||||
let (base_rev_id, rev_id) = first_revision.pair_rev_id();
|
||||
let md5 = last_revision.md5.clone();
|
||||
struct FolderRevisionCompactor();
|
||||
impl RevisionCompactor for FolderRevisionCompactor {
|
||||
fn bytes_from_revisions(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes> {
|
||||
let delta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
let delta_data = delta.to_bytes();
|
||||
Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5))
|
||||
Ok(delta.to_bytes())
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ use flowy_folder_data_model::entities::{
|
||||
view::{RepeatedView, View},
|
||||
workspace::Workspace,
|
||||
};
|
||||
use flowy_sync::disk::SQLiteTextBlockRevisionPersistence;
|
||||
use flowy_sync::{RevisionLoader, RevisionPersistence};
|
||||
use std::sync::Arc;
|
||||
|
||||
@ -87,7 +88,8 @@ impl FolderMigration {
|
||||
return Ok(None);
|
||||
}
|
||||
let pool = self.database.db_pool()?;
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), pool.clone()));
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(&user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(user_id, folder_id.as_ref(), disk_cache));
|
||||
let (revisions, _) = RevisionLoader {
|
||||
object_id: folder_id.as_ref().to_owned(),
|
||||
user_id: self.user_id.clone(),
|
||||
|
@ -7,6 +7,7 @@ use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{Field, RowMeta};
|
||||
use flowy_sync::{RevisionManager, RevisionPersistence, RevisionWebSocket};
|
||||
|
||||
use flowy_sync::disk::SQLiteGridRevisionPersistence;
|
||||
use lib_sqlite::ConnectionPool;
|
||||
use parking_lot::RwLock;
|
||||
use std::sync::Arc;
|
||||
@ -104,7 +105,9 @@ impl GridManager {
|
||||
|
||||
fn make_grid_rev_manager(&self, grid_id: &str, pool: Arc<ConnectionPool>) -> FlowyResult<RevisionManager> {
|
||||
let user_id = self.grid_user.user_id()?;
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, grid_id, pool));
|
||||
|
||||
let disk_cache = Arc::new(SQLiteGridRevisionPersistence::new(&user_id, pool));
|
||||
let rev_persistence = Arc::new(RevisionPersistence::new(&user_id, grid_id, disk_cache));
|
||||
let rev_manager = RevisionManager::new(&user_id, grid_id, rev_persistence);
|
||||
Ok(rev_manager)
|
||||
}
|
||||
|
@ -2,6 +2,8 @@ use crate::manager::GridUser;
|
||||
use crate::services::kv_persistence::{GridKVPersistence, KVTransaction};
|
||||
use crate::services::stringify::stringify_deserialize;
|
||||
|
||||
use crate::services::grid_meta_editor::ClientGridBlockMetaEditor;
|
||||
use bytes::Bytes;
|
||||
use dashmap::DashMap;
|
||||
use flowy_collaboration::client_grid::{GridChange, GridMetaPad};
|
||||
use flowy_collaboration::entities::revision::Revision;
|
||||
@ -10,10 +12,10 @@ use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::{
|
||||
Cell, CellMeta, Field, Grid, RepeatedField, RepeatedFieldOrder, RepeatedRow, RepeatedRowOrder, Row, RowMeta,
|
||||
};
|
||||
use flowy_sync::{RevisionCloudService, RevisionCompact, RevisionManager, RevisionObjectBuilder};
|
||||
use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
use lib_ot::core::{Delta, PlainTextAttributes};
|
||||
use rayon::iter::{IntoParallelIterator, ParallelIterator};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
@ -24,10 +26,8 @@ pub struct ClientGridEditor {
|
||||
user: Arc<dyn GridUser>,
|
||||
grid_meta_pad: Arc<RwLock<GridMetaPad>>,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
block_meta_manager: Arc<GridBlockMetaEditorManager>,
|
||||
kv_persistence: Arc<GridKVPersistence>,
|
||||
|
||||
field_map: DashMap<String, Field>,
|
||||
cell_map: DashMap<String, CellMeta>,
|
||||
}
|
||||
|
||||
impl ClientGridEditor {
|
||||
@ -39,50 +39,22 @@ impl ClientGridEditor {
|
||||
) -> FlowyResult<Arc<Self>> {
|
||||
let token = user.token()?;
|
||||
let cloud = Arc::new(GridRevisionCloudService { token });
|
||||
let grid_pad = rev_manager.load::<GridPadBuilder, GridRevisionCompact>(cloud).await?;
|
||||
let grid_pad = rev_manager.load::<GridPadBuilder>(cloud).await?;
|
||||
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let field_map = load_all_fields(&grid_pad, &kv_persistence).await?;
|
||||
let grid_meta_pad = Arc::new(RwLock::new(grid_pad));
|
||||
let cell_map = DashMap::new();
|
||||
let block_meta_manager = Arc::new(GridBlockMetaEditorManager::new());
|
||||
|
||||
Ok(Arc::new(Self {
|
||||
grid_id: grid_id.to_owned(),
|
||||
user,
|
||||
grid_meta_pad,
|
||||
rev_manager,
|
||||
block_meta_manager,
|
||||
kv_persistence,
|
||||
field_map,
|
||||
cell_map,
|
||||
}))
|
||||
}
|
||||
|
||||
pub async fn create_empty_row(&self) -> FlowyResult<()> {
|
||||
let row = RowMeta::new(&uuid(), &self.grid_id, vec![]);
|
||||
self.create_row(row).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_row(&self, row: RowMeta) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.create_row(row)?)).await?;
|
||||
// self.cell_map.insert(row.id.clone(), row.clone());
|
||||
// let _ = self.kv_persistence.set(row)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.delete_rows(&ids)?)).await?;
|
||||
// let _ = self.kv.batch_delete(ids)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
// pub async fn update_row(&self, cell: Cell) -> FlowyResult<()> {
|
||||
// match self.cell_map.get(&cell.id) {
|
||||
// None => Err(FlowyError::internal().context(format!("Can't find cell with id: {}", cell.id))),
|
||||
// Some(raw_cell) => {}
|
||||
// }
|
||||
// }
|
||||
|
||||
pub async fn create_field(&mut self, field: Field) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.create_field(field)?)).await?;
|
||||
Ok(())
|
||||
@ -90,76 +62,38 @@ impl ClientGridEditor {
|
||||
|
||||
pub async fn delete_field(&mut self, field_id: &str) -> FlowyResult<()> {
|
||||
let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?;
|
||||
// let _ = self.kv.remove(field_id)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
let ids = row_orders
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|row_order| row_order.row_id)
|
||||
.collect::<Vec<_>>();
|
||||
let row_metas: Vec<RowMeta> = self.kv_persistence.batch_get(ids)?;
|
||||
|
||||
let make_cell = |field_id: String, raw_cell: CellMeta| {
|
||||
let some_field = self.field_map.get(&field_id);
|
||||
if some_field.is_none() {
|
||||
tracing::error!("Can't find the field with {}", field_id);
|
||||
return None;
|
||||
}
|
||||
self.cell_map.insert(raw_cell.id.clone(), raw_cell.clone());
|
||||
|
||||
let field = some_field.unwrap();
|
||||
match stringify_deserialize(raw_cell.data, field.value()) {
|
||||
Ok(content) => {
|
||||
let cell = Cell {
|
||||
id: raw_cell.id,
|
||||
field_id: field_id.clone(),
|
||||
content,
|
||||
};
|
||||
Some((field_id, cell))
|
||||
}
|
||||
Err(_) => None,
|
||||
}
|
||||
};
|
||||
|
||||
let rows = row_metas
|
||||
.into_par_iter()
|
||||
.map(|row_meta| {
|
||||
let mut row = Row {
|
||||
id: row_meta.id.clone(),
|
||||
cell_by_field_id: Default::default(),
|
||||
height: row_meta.height,
|
||||
};
|
||||
row.cell_by_field_id = row_meta
|
||||
.cell_by_field_id
|
||||
.into_par_iter()
|
||||
.flat_map(|(field_id, raw_cell)| make_cell(field_id, raw_cell))
|
||||
.collect::<HashMap<String, Cell>>();
|
||||
row
|
||||
})
|
||||
.collect::<Vec<Row>>();
|
||||
|
||||
Ok(rows.into())
|
||||
pub async fn create_empty_row(&self) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| {
|
||||
//
|
||||
//
|
||||
// grid.blocks
|
||||
//
|
||||
// }).await?;
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn get_fields(&self, field_orders: RepeatedFieldOrder) -> FlowyResult<RepeatedField> {
|
||||
let fields = field_orders
|
||||
.iter()
|
||||
.flat_map(|field_order| match self.field_map.get(&field_order.field_id) {
|
||||
None => {
|
||||
tracing::error!("Can't find the field with {}", field_order.field_id);
|
||||
None
|
||||
}
|
||||
Some(field) => Some(field.value().clone()),
|
||||
})
|
||||
.collect::<Vec<Field>>();
|
||||
Ok(fields.into())
|
||||
async fn create_row(&self, row: RowMeta) -> FlowyResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn grid_data(&self) -> Grid {
|
||||
self.grid_meta_pad.read().await.grid_data()
|
||||
todo!()
|
||||
}
|
||||
|
||||
pub async fn get_fields(&self, field_orders: RepeatedFieldOrder) -> FlowyResult<RepeatedField> {
|
||||
let fields = self.grid_meta_pad.read().await.get_fields(field_orders)?;
|
||||
Ok(fields)
|
||||
}
|
||||
|
||||
pub async fn delta_str(&self) -> String {
|
||||
@ -195,7 +129,7 @@ impl ClientGridEditor {
|
||||
);
|
||||
let _ = self
|
||||
.rev_manager
|
||||
.add_local_revision::<GridRevisionCompact>(&revision)
|
||||
.add_local_revision(&revision, Box::new(GridRevisionCompactor()))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
@ -241,24 +175,73 @@ impl RevisionCloudService for GridRevisionCloudService {
|
||||
}
|
||||
}
|
||||
|
||||
struct GridRevisionCompact();
|
||||
impl RevisionCompact for GridRevisionCompact {
|
||||
fn compact_revisions(user_id: &str, object_id: &str, mut revisions: Vec<Revision>) -> FlowyResult<Revision> {
|
||||
if revisions.is_empty() {
|
||||
return Err(FlowyError::internal().context("Can't compact the empty folder's revisions"));
|
||||
}
|
||||
|
||||
if revisions.len() == 1 {
|
||||
return Ok(revisions.pop().unwrap());
|
||||
}
|
||||
|
||||
let first_revision = revisions.first().unwrap();
|
||||
let last_revision = revisions.last().unwrap();
|
||||
|
||||
let (base_rev_id, rev_id) = first_revision.pair_rev_id();
|
||||
let md5 = last_revision.md5.clone();
|
||||
struct GridRevisionCompactor();
|
||||
impl RevisionCompactor for GridRevisionCompactor {
|
||||
fn bytes_from_revisions(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes> {
|
||||
let delta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
let delta_data = delta.to_bytes();
|
||||
Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5))
|
||||
Ok(delta.to_bytes())
|
||||
}
|
||||
}
|
||||
|
||||
struct GridBlockMetaEditorManager {
|
||||
editor_map: DashMap<String, Arc<ClientGridBlockMetaEditor>>,
|
||||
}
|
||||
|
||||
impl GridBlockMetaEditorManager {
|
||||
fn new() -> Self {
|
||||
Self {
|
||||
editor_map: DashMap::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn get_rows(&self, row_orders: RepeatedRowOrder) -> FlowyResult<RepeatedRow> {
|
||||
// let ids = row_orders
|
||||
// .items
|
||||
// .into_iter()
|
||||
// .map(|row_order| row_order.row_id)
|
||||
// .collect::<Vec<_>>();
|
||||
// let row_metas: Vec<RowMeta> = self.kv_persistence.batch_get(ids)?;
|
||||
//
|
||||
// let make_cell = |field_id: String, raw_cell: CellMeta| {
|
||||
// let some_field = self.field_map.get(&field_id);
|
||||
// if some_field.is_none() {
|
||||
// tracing::error!("Can't find the field with {}", field_id);
|
||||
// return None;
|
||||
// }
|
||||
// self.cell_map.insert(raw_cell.id.clone(), raw_cell.clone());
|
||||
//
|
||||
// let field = some_field.unwrap();
|
||||
// match stringify_deserialize(raw_cell.data, field.value()) {
|
||||
// Ok(content) => {
|
||||
// let cell = Cell {
|
||||
// id: raw_cell.id,
|
||||
// field_id: field_id.clone(),
|
||||
// content,
|
||||
// };
|
||||
// Some((field_id, cell))
|
||||
// }
|
||||
// Err(_) => None,
|
||||
// }
|
||||
// };
|
||||
//
|
||||
// let rows = row_metas
|
||||
// .into_par_iter()
|
||||
// .map(|row_meta| {
|
||||
// let mut row = Row {
|
||||
// id: row_meta.id.clone(),
|
||||
// cell_by_field_id: Default::default(),
|
||||
// height: row_meta.height,
|
||||
// };
|
||||
// row.cell_by_field_id = row_meta
|
||||
// .cell_by_field_id
|
||||
// .into_par_iter()
|
||||
// .flat_map(|(field_id, raw_cell)| make_cell(field_id, raw_cell))
|
||||
// .collect::<HashMap<String, Cell>>();
|
||||
// row
|
||||
// })
|
||||
// .collect::<Vec<Row>>();
|
||||
//
|
||||
// Ok(rows.into())
|
||||
todo!()
|
||||
}
|
||||
}
|
||||
|
125
frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs
Normal file
125
frontend/rust-lib/flowy-grid/src/services/grid_meta_editor.rs
Normal file
@ -0,0 +1,125 @@
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::client_grid::{GridBlockMetaChange, GridBlockMetaPad};
|
||||
use flowy_collaboration::entities::revision::Revision;
|
||||
use flowy_collaboration::util::make_delta_from_revisions;
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use flowy_grid_data_model::entities::RowMeta;
|
||||
use flowy_sync::{RevisionCloudService, RevisionCompactor, RevisionManager, RevisionObjectBuilder};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::PlainTextAttributes;
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::RwLock;
|
||||
|
||||
pub struct ClientGridBlockMetaEditor {
|
||||
user_id: String,
|
||||
block_id: String,
|
||||
meta_pad: Arc<RwLock<GridBlockMetaPad>>,
|
||||
rev_manager: Arc<RevisionManager>,
|
||||
}
|
||||
|
||||
impl ClientGridBlockMetaEditor {
|
||||
pub async fn new(
|
||||
user_id: &str,
|
||||
token: &str,
|
||||
block_id: String,
|
||||
mut rev_manager: RevisionManager,
|
||||
) -> FlowyResult<Self> {
|
||||
let cloud = Arc::new(GridBlockMetaRevisionCloudService {
|
||||
token: token.to_owned(),
|
||||
});
|
||||
let block_meta_pad = rev_manager.load::<GridBlockMetaPadBuilder>(cloud).await?;
|
||||
let meta_pad = Arc::new(RwLock::new(block_meta_pad));
|
||||
let rev_manager = Arc::new(rev_manager);
|
||||
let user_id = user_id.to_owned();
|
||||
Ok(Self {
|
||||
user_id,
|
||||
block_id,
|
||||
meta_pad,
|
||||
rev_manager,
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn create_empty_row(&self) -> FlowyResult<()> {
|
||||
let row = RowMeta::new(&uuid(), &self.block_id, vec![]);
|
||||
self.create_row(row).await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn create_row(&self, row: RowMeta) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| Ok(grid.create_row(row)?)).await?;
|
||||
// self.cell_map.insert(row.id.clone(), row.clone());
|
||||
// let _ = self.kv_persistence.set(row)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn delete_rows(&self, ids: Vec<String>) -> FlowyResult<()> {
|
||||
// let _ = self.modify(|grid| Ok(grid.delete_rows(&ids)?)).await?;
|
||||
// let _ = self.kv.batch_delete(ids)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn modify<F>(&self, f: F) -> FlowyResult<()>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut GridBlockMetaPad) -> FlowyResult<Option<GridBlockMetaChange>>,
|
||||
{
|
||||
let mut write_guard = self.meta_pad.write().await;
|
||||
match f(&mut *write_guard)? {
|
||||
None => {}
|
||||
Some(change) => {
|
||||
let _ = self.apply_change(change).await?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn apply_change(&self, change: GridBlockMetaChange) -> FlowyResult<()> {
|
||||
let GridBlockMetaChange { delta, md5 } = change;
|
||||
let user_id = self.user_id.clone();
|
||||
let (base_rev_id, rev_id) = self.rev_manager.next_rev_id_pair();
|
||||
let delta_data = delta.to_bytes();
|
||||
let revision = Revision::new(
|
||||
&self.rev_manager.object_id,
|
||||
base_rev_id,
|
||||
rev_id,
|
||||
delta_data,
|
||||
&user_id,
|
||||
md5,
|
||||
);
|
||||
let _ = self
|
||||
.rev_manager
|
||||
.add_local_revision(&revision, Box::new(GridBlockMetaRevisionCompactor()))
|
||||
.await?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct GridBlockMetaRevisionCloudService {
|
||||
#[allow(dead_code)]
|
||||
token: String,
|
||||
}
|
||||
|
||||
impl RevisionCloudService for GridBlockMetaRevisionCloudService {
|
||||
#[tracing::instrument(level = "trace", skip(self))]
|
||||
fn fetch_object(&self, _user_id: &str, _object_id: &str) -> FutureResult<Vec<Revision>, FlowyError> {
|
||||
FutureResult::new(async move { Ok(vec![]) })
|
||||
}
|
||||
}
|
||||
|
||||
struct GridBlockMetaPadBuilder();
|
||||
impl RevisionObjectBuilder for GridBlockMetaPadBuilder {
|
||||
type Output = GridBlockMetaPad;
|
||||
|
||||
fn build_object(object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output> {
|
||||
let pad = GridBlockMetaPad::from_revisions(object_id, revisions)?;
|
||||
Ok(pad)
|
||||
}
|
||||
}
|
||||
|
||||
struct GridBlockMetaRevisionCompactor();
|
||||
impl RevisionCompactor for GridBlockMetaRevisionCompactor {
|
||||
fn bytes_from_revisions(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes> {
|
||||
let delta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
Ok(delta.to_bytes())
|
||||
}
|
||||
}
|
@ -3,5 +3,6 @@ mod util;
|
||||
pub mod cell_data;
|
||||
pub mod grid_builder;
|
||||
pub mod grid_editor;
|
||||
pub mod grid_meta_editor;
|
||||
pub mod kv_persistence;
|
||||
pub mod stringify;
|
||||
|
@ -66,10 +66,10 @@ fn make_view_data_processor(
|
||||
) -> ViewDataProcessorMap {
|
||||
let mut map: HashMap<ViewDataType, Arc<dyn ViewDataProcessor + Send + Sync>> = HashMap::new();
|
||||
|
||||
let block_data_impl = BlockManagerViewDataImpl(text_block_manager);
|
||||
let block_data_impl = TextBlockViewDataProcessor(text_block_manager);
|
||||
map.insert(block_data_impl.data_type(), Arc::new(block_data_impl));
|
||||
|
||||
let grid_data_impl = GridManagerViewDataImpl(grid_manager);
|
||||
let grid_data_impl = GridViewDataProcessor(grid_manager);
|
||||
map.insert(grid_data_impl.data_type(), Arc::new(grid_data_impl));
|
||||
|
||||
Arc::new(map)
|
||||
@ -133,8 +133,8 @@ impl WSMessageReceiver for FolderWSMessageReceiverImpl {
|
||||
}
|
||||
}
|
||||
|
||||
struct BlockManagerViewDataImpl(Arc<TextBlockManager>);
|
||||
impl ViewDataProcessor for BlockManagerViewDataImpl {
|
||||
struct TextBlockViewDataProcessor(Arc<TextBlockManager>);
|
||||
impl ViewDataProcessor for TextBlockViewDataProcessor {
|
||||
fn initialize(&self) -> FutureResult<(), FlowyError> {
|
||||
let manager = self.0.clone();
|
||||
FutureResult::new(async move { manager.init() })
|
||||
@ -186,8 +186,8 @@ impl ViewDataProcessor for BlockManagerViewDataImpl {
|
||||
}
|
||||
}
|
||||
|
||||
struct GridManagerViewDataImpl(Arc<GridManager>);
|
||||
impl ViewDataProcessor for GridManagerViewDataImpl {
|
||||
struct GridViewDataProcessor(Arc<GridManager>);
|
||||
impl ViewDataProcessor for GridViewDataProcessor {
|
||||
fn initialize(&self) -> FutureResult<(), FlowyError> {
|
||||
FutureResult::new(async { Ok(()) })
|
||||
}
|
||||
|
235
frontend/rust-lib/flowy-sync/src/cache/disk/grid_meta_rev_impl.rs
vendored
Normal file
235
frontend/rust-lib/flowy-sync/src/cache/disk/grid_meta_rev_impl.rs
vendored
Normal file
@ -0,0 +1,235 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
entities::revision::{RevId, RevType, Revision, RevisionRange},
|
||||
util::md5,
|
||||
};
|
||||
use flowy_database::{
|
||||
impl_sql_integer_expression, insert_or_ignore_into,
|
||||
prelude::*,
|
||||
schema::{grid_meta_rev_table, grid_meta_rev_table::dsl},
|
||||
ConnectionPool,
|
||||
};
|
||||
use flowy_error::{internal_error, FlowyError, FlowyResult};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct SQLiteGridBlockMetaRevisionPersistence {
|
||||
user_id: String,
|
||||
pub(crate) pool: Arc<ConnectionPool>,
|
||||
}
|
||||
|
||||
impl RevisionDiskCache for SQLiteGridBlockMetaRevisionPersistence {
|
||||
type Error = FlowyError;
|
||||
|
||||
fn create_revision_records(&self, revision_records: Vec<RevisionRecord>) -> Result<(), Self::Error> {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
let _ = GridMetaRevisionSql::create(revision_records, &*conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read_revision_records(
|
||||
&self,
|
||||
object_id: &str,
|
||||
rev_ids: Option<Vec<i64>>,
|
||||
) -> Result<Vec<RevisionRecord>, Self::Error> {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
let records = GridMetaRevisionSql::read(&self.user_id, object_id, rev_ids, &*conn)?;
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
fn read_revision_records_with_range(
|
||||
&self,
|
||||
object_id: &str,
|
||||
range: &RevisionRange,
|
||||
) -> Result<Vec<RevisionRecord>, Self::Error> {
|
||||
let conn = &*self.pool.get().map_err(internal_error)?;
|
||||
let revisions = GridMetaRevisionSql::read_with_range(&self.user_id, object_id, range.clone(), conn)?;
|
||||
Ok(revisions)
|
||||
}
|
||||
|
||||
fn update_revision_record(&self, changesets: Vec<RevisionChangeset>) -> FlowyResult<()> {
|
||||
let conn = &*self.pool.get().map_err(internal_error)?;
|
||||
let _ = conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
for changeset in changesets {
|
||||
let _ = GridMetaRevisionSql::update(changeset, conn)?;
|
||||
}
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_revision_records(&self, object_id: &str, rev_ids: Option<Vec<i64>>) -> Result<(), Self::Error> {
|
||||
let conn = &*self.pool.get().map_err(internal_error)?;
|
||||
let _ = GridMetaRevisionSql::delete(object_id, rev_ids, conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn delete_and_insert_records(
|
||||
&self,
|
||||
object_id: &str,
|
||||
deleted_rev_ids: Option<Vec<i64>>,
|
||||
inserted_records: Vec<RevisionRecord>,
|
||||
) -> Result<(), Self::Error> {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
let _ = GridMetaRevisionSql::delete(object_id, deleted_rev_ids, &*conn)?;
|
||||
let _ = GridMetaRevisionSql::create(inserted_records, &*conn)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SQLiteGridBlockMetaRevisionPersistence {
|
||||
pub fn new(user_id: &str, pool: Arc<ConnectionPool>) -> Self {
|
||||
Self {
|
||||
user_id: user_id.to_owned(),
|
||||
pool,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct GridMetaRevisionSql();
|
||||
impl GridMetaRevisionSql {
|
||||
fn create(revision_records: Vec<RevisionRecord>, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
// Batch insert: https://diesel.rs/guides/all-about-inserts.html
|
||||
|
||||
let records = revision_records
|
||||
.into_iter()
|
||||
.map(|record| {
|
||||
tracing::trace!(
|
||||
"[GridMetaRevisionSql] create revision: {}:{:?}",
|
||||
record.revision.object_id,
|
||||
record.revision.rev_id
|
||||
);
|
||||
let rev_state: GridMetaRevisionState = record.state.into();
|
||||
(
|
||||
dsl::object_id.eq(record.revision.object_id),
|
||||
dsl::base_rev_id.eq(record.revision.base_rev_id),
|
||||
dsl::rev_id.eq(record.revision.rev_id),
|
||||
dsl::data.eq(record.revision.delta_data),
|
||||
dsl::state.eq(rev_state),
|
||||
)
|
||||
})
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
let _ = insert_or_ignore_into(dsl::grid_meta_rev_table)
|
||||
.values(&records)
|
||||
.execute(conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn update(changeset: RevisionChangeset, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let state: GridMetaRevisionState = changeset.state.clone().into();
|
||||
let filter = dsl::grid_meta_rev_table
|
||||
.filter(dsl::rev_id.eq(changeset.rev_id.as_ref()))
|
||||
.filter(dsl::object_id.eq(changeset.object_id));
|
||||
let _ = update(filter).set(dsl::state.eq(state)).execute(conn)?;
|
||||
tracing::debug!(
|
||||
"[GridMetaRevisionSql] update revision:{} state:to {:?}",
|
||||
changeset.rev_id,
|
||||
changeset.state
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn read(
|
||||
user_id: &str,
|
||||
object_id: &str,
|
||||
rev_ids: Option<Vec<i64>>,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<Vec<RevisionRecord>, FlowyError> {
|
||||
let mut sql = dsl::grid_meta_rev_table
|
||||
.filter(dsl::object_id.eq(object_id))
|
||||
.into_boxed();
|
||||
if let Some(rev_ids) = rev_ids {
|
||||
sql = sql.filter(dsl::rev_id.eq_any(rev_ids));
|
||||
}
|
||||
let rows = sql.order(dsl::rev_id.asc()).load::<GridMetaRevisionTable>(conn)?;
|
||||
let records = rows
|
||||
.into_iter()
|
||||
.map(|row| mk_revision_record_from_table(user_id, row))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
Ok(records)
|
||||
}
|
||||
|
||||
fn read_with_range(
|
||||
user_id: &str,
|
||||
object_id: &str,
|
||||
range: RevisionRange,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<Vec<RevisionRecord>, FlowyError> {
|
||||
let rev_tables = dsl::grid_meta_rev_table
|
||||
.filter(dsl::rev_id.ge(range.start))
|
||||
.filter(dsl::rev_id.le(range.end))
|
||||
.filter(dsl::object_id.eq(object_id))
|
||||
.order(dsl::rev_id.asc())
|
||||
.load::<GridMetaRevisionTable>(conn)?;
|
||||
|
||||
let revisions = rev_tables
|
||||
.into_iter()
|
||||
.map(|table| mk_revision_record_from_table(user_id, table))
|
||||
.collect::<Vec<_>>();
|
||||
Ok(revisions)
|
||||
}
|
||||
|
||||
fn delete(object_id: &str, rev_ids: Option<Vec<i64>>, conn: &SqliteConnection) -> Result<(), FlowyError> {
|
||||
let mut sql = diesel::delete(dsl::grid_meta_rev_table).into_boxed();
|
||||
sql = sql.filter(dsl::object_id.eq(object_id));
|
||||
|
||||
if let Some(rev_ids) = rev_ids {
|
||||
tracing::trace!("[GridMetaRevisionSql] Delete revision: {}:{:?}", object_id, rev_ids);
|
||||
sql = sql.filter(dsl::rev_id.eq_any(rev_ids));
|
||||
}
|
||||
|
||||
let affected_row = sql.execute(conn)?;
|
||||
tracing::trace!("[GridMetaRevisionSql] Delete {} rows", affected_row);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||
#[table_name = "grid_meta_rev_table"]
|
||||
struct GridMetaRevisionTable {
|
||||
id: i32,
|
||||
object_id: String,
|
||||
base_rev_id: i64,
|
||||
rev_id: i64,
|
||||
data: Vec<u8>,
|
||||
state: GridMetaRevisionState,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)]
|
||||
#[repr(i32)]
|
||||
#[sql_type = "Integer"]
|
||||
pub enum GridMetaRevisionState {
|
||||
Sync = 0,
|
||||
Ack = 1,
|
||||
}
|
||||
impl_sql_integer_expression!(GridMetaRevisionState);
|
||||
impl_rev_state_map!(GridMetaRevisionState);
|
||||
impl std::default::Default for GridMetaRevisionState {
|
||||
fn default() -> Self {
|
||||
GridMetaRevisionState::Sync
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_revision_record_from_table(user_id: &str, table: GridMetaRevisionTable) -> RevisionRecord {
|
||||
let md5 = md5(&table.data);
|
||||
let revision = Revision::new(
|
||||
&table.object_id,
|
||||
table.base_rev_id,
|
||||
table.rev_id,
|
||||
Bytes::from(table.data),
|
||||
user_id,
|
||||
md5,
|
||||
);
|
||||
RevisionRecord {
|
||||
revision,
|
||||
state: table.state.into(),
|
||||
write_to_disk: false,
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
@ -23,12 +24,9 @@ pub struct SQLiteGridRevisionPersistence {
|
||||
impl RevisionDiskCache for SQLiteGridRevisionPersistence {
|
||||
type Error = FlowyError;
|
||||
|
||||
fn create_revision_records(
|
||||
&self,
|
||||
revision_records: Vec<RevisionRecord>,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<(), Self::Error> {
|
||||
let _ = GridRevisionSql::create(revision_records, conn)?;
|
||||
fn create_revision_records(&self, revision_records: Vec<RevisionRecord>) -> Result<(), Self::Error> {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
let _ = GridRevisionSql::create(revision_records, &*conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -78,14 +76,14 @@ impl RevisionDiskCache for SQLiteGridRevisionPersistence {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
let _ = GridRevisionSql::delete(object_id, deleted_rev_ids, &*conn)?;
|
||||
let _ = self.create_revision_records(inserted_records, &*conn)?;
|
||||
let _ = GridRevisionSql::create(inserted_records, &*conn)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SQLiteGridRevisionPersistence {
|
||||
pub(crate) fn new(user_id: &str, pool: Arc<ConnectionPool>) -> Self {
|
||||
pub fn new(user_id: &str, pool: Arc<ConnectionPool>) -> Self {
|
||||
Self {
|
||||
user_id: user_id.to_owned(),
|
||||
pool,
|
||||
@ -193,13 +191,13 @@ impl GridRevisionSql {
|
||||
|
||||
#[derive(PartialEq, Clone, Debug, Queryable, Identifiable, Insertable, Associations)]
|
||||
#[table_name = "grid_rev_table"]
|
||||
pub(crate) struct GridRevisionTable {
|
||||
struct GridRevisionTable {
|
||||
id: i32,
|
||||
pub(crate) object_id: String,
|
||||
pub(crate) base_rev_id: i64,
|
||||
pub(crate) rev_id: i64,
|
||||
pub(crate) data: Vec<u8>,
|
||||
pub(crate) state: GridRevisionState,
|
||||
object_id: String,
|
||||
base_rev_id: i64,
|
||||
rev_id: i64,
|
||||
data: Vec<u8>,
|
||||
state: GridRevisionState,
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Hash, FromSqlRow, AsExpression)]
|
||||
@ -209,6 +207,8 @@ pub enum GridRevisionState {
|
||||
Sync = 0,
|
||||
Ack = 1,
|
||||
}
|
||||
impl_sql_integer_expression!(GridRevisionState);
|
||||
impl_rev_state_map!(GridRevisionState);
|
||||
|
||||
impl std::default::Default for GridRevisionState {
|
||||
fn default() -> Self {
|
||||
@ -216,44 +216,6 @@ impl std::default::Default for GridRevisionState {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<i32> for GridRevisionState {
|
||||
fn from(value: i32) -> Self {
|
||||
match value {
|
||||
0 => GridRevisionState::Sync,
|
||||
1 => GridRevisionState::Ack,
|
||||
o => {
|
||||
tracing::error!("Unsupported rev state {}, fallback to RevState::Local", o);
|
||||
GridRevisionState::Sync
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl GridRevisionState {
|
||||
pub fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
}
|
||||
impl_sql_integer_expression!(GridRevisionState);
|
||||
|
||||
impl std::convert::From<GridRevisionState> for RevisionState {
|
||||
fn from(s: GridRevisionState) -> Self {
|
||||
match s {
|
||||
GridRevisionState::Sync => RevisionState::Sync,
|
||||
GridRevisionState::Ack => RevisionState::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<RevisionState> for GridRevisionState {
|
||||
fn from(s: RevisionState) -> Self {
|
||||
match s {
|
||||
RevisionState::Sync => GridRevisionState::Sync,
|
||||
RevisionState::Ack => GridRevisionState::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_revision_record_from_table(user_id: &str, table: GridRevisionTable) -> RevisionRecord {
|
||||
let md5 = md5(&table.data);
|
||||
let revision = Revision::new(
|
||||
|
@ -1,11 +1,14 @@
|
||||
mod folder_rev_impl;
|
||||
mod grid_meta_rev_impl;
|
||||
mod grid_rev_impl;
|
||||
mod text_rev_impl;
|
||||
|
||||
pub use folder_rev_impl::*;
|
||||
pub use grid_meta_rev_impl::*;
|
||||
pub use grid_rev_impl::*;
|
||||
pub use text_rev_impl::*;
|
||||
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
use diesel::SqliteConnection;
|
||||
use flowy_collaboration::entities::revision::{RevId, Revision, RevisionRange};
|
||||
use flowy_error::FlowyResult;
|
||||
@ -13,11 +16,7 @@ use std::fmt::Debug;
|
||||
|
||||
pub trait RevisionDiskCache: Sync + Send {
|
||||
type Error: Debug;
|
||||
fn create_revision_records(
|
||||
&self,
|
||||
revision_records: Vec<RevisionRecord>,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<(), Self::Error>;
|
||||
fn create_revision_records(&self, revision_records: Vec<RevisionRecord>) -> Result<(), Self::Error>;
|
||||
|
||||
// Read all the records if the rev_ids is None
|
||||
fn read_revision_records(
|
||||
|
@ -1,5 +1,6 @@
|
||||
use crate::cache::disk::RevisionDiskCache;
|
||||
use crate::disk::{RevisionChangeset, RevisionRecord, RevisionState};
|
||||
use crate::memory::RevisionMemoryCacheDelegate;
|
||||
use bytes::Bytes;
|
||||
use diesel::{sql_types::Integer, update, SqliteConnection};
|
||||
use flowy_collaboration::{
|
||||
@ -23,12 +24,9 @@ pub struct SQLiteTextBlockRevisionPersistence {
|
||||
impl RevisionDiskCache for SQLiteTextBlockRevisionPersistence {
|
||||
type Error = FlowyError;
|
||||
|
||||
fn create_revision_records(
|
||||
&self,
|
||||
revision_records: Vec<RevisionRecord>,
|
||||
conn: &SqliteConnection,
|
||||
) -> Result<(), Self::Error> {
|
||||
let _ = TextRevisionSql::create(revision_records, conn)?;
|
||||
fn create_revision_records(&self, revision_records: Vec<RevisionRecord>) -> Result<(), Self::Error> {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
let _ = TextRevisionSql::create(revision_records, &*conn)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -78,14 +76,14 @@ impl RevisionDiskCache for SQLiteTextBlockRevisionPersistence {
|
||||
let conn = self.pool.get().map_err(internal_error)?;
|
||||
conn.immediate_transaction::<_, FlowyError, _>(|| {
|
||||
let _ = TextRevisionSql::delete(object_id, deleted_rev_ids, &*conn)?;
|
||||
let _ = self.create_revision_records(inserted_records, &*conn)?;
|
||||
let _ = TextRevisionSql::create(inserted_records, &*conn)?;
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl SQLiteTextBlockRevisionPersistence {
|
||||
pub(crate) fn new(user_id: &str, pool: Arc<ConnectionPool>) -> Self {
|
||||
pub fn new(user_id: &str, pool: Arc<ConnectionPool>) -> Self {
|
||||
Self {
|
||||
user_id: user_id.to_owned(),
|
||||
pool,
|
||||
@ -210,6 +208,8 @@ enum TextRevisionState {
|
||||
Sync = 0,
|
||||
Ack = 1,
|
||||
}
|
||||
impl_sql_integer_expression!(TextRevisionState);
|
||||
impl_rev_state_map!(TextRevisionState);
|
||||
|
||||
impl std::default::Default for TextRevisionState {
|
||||
fn default() -> Self {
|
||||
@ -217,44 +217,6 @@ impl std::default::Default for TextRevisionState {
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<i32> for TextRevisionState {
|
||||
fn from(value: i32) -> Self {
|
||||
match value {
|
||||
0 => TextRevisionState::Sync,
|
||||
1 => TextRevisionState::Ack,
|
||||
o => {
|
||||
tracing::error!("Unsupported rev state {}, fallback to RevState::Local", o);
|
||||
TextRevisionState::Sync
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl TextRevisionState {
|
||||
pub fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
}
|
||||
impl_sql_integer_expression!(TextRevisionState);
|
||||
|
||||
impl std::convert::From<TextRevisionState> for RevisionState {
|
||||
fn from(s: TextRevisionState) -> Self {
|
||||
match s {
|
||||
TextRevisionState::Sync => RevisionState::Sync,
|
||||
TextRevisionState::Ack => RevisionState::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::convert::From<RevisionState> for TextRevisionState {
|
||||
fn from(s: RevisionState) -> Self {
|
||||
match s {
|
||||
RevisionState::Sync => TextRevisionState::Sync,
|
||||
RevisionState::Ack => TextRevisionState::Ack,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn mk_revision_record_from_table(user_id: &str, table: RevisionTable) -> RevisionRecord {
|
||||
let md5 = md5(&table.data);
|
||||
let revision = Revision::new(
|
||||
@ -279,6 +241,7 @@ pub enum RevTableType {
|
||||
Local = 0,
|
||||
Remote = 1,
|
||||
}
|
||||
impl_sql_integer_expression!(RevTableType);
|
||||
|
||||
impl std::default::Default for RevTableType {
|
||||
fn default() -> Self {
|
||||
@ -298,12 +261,6 @@ impl std::convert::From<i32> for RevTableType {
|
||||
}
|
||||
}
|
||||
}
|
||||
impl RevTableType {
|
||||
pub fn value(&self) -> i32 {
|
||||
*self as i32
|
||||
}
|
||||
}
|
||||
impl_sql_integer_expression!(RevTableType);
|
||||
|
||||
impl std::convert::From<RevType> for RevTableType {
|
||||
fn from(ty: RevType) -> Self {
|
||||
|
@ -1,11 +1,13 @@
|
||||
use crate::disk::RevisionState;
|
||||
use crate::{RevisionPersistence, WSDataProviderDataSource};
|
||||
use bytes::Bytes;
|
||||
use flowy_collaboration::{
|
||||
entities::revision::{RepeatedRevision, Revision, RevisionRange},
|
||||
util::{pair_rev_id_from_revisions, RevIdCounter},
|
||||
};
|
||||
use flowy_error::{FlowyError, FlowyResult};
|
||||
use lib_infra::future::FutureResult;
|
||||
use lib_ot::core::{Attributes, Delta};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub trait RevisionCloudService: Send + Sync {
|
||||
@ -17,8 +19,26 @@ pub trait RevisionObjectBuilder: Send + Sync {
|
||||
fn build_object(object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Self::Output>;
|
||||
}
|
||||
|
||||
pub trait RevisionCompact: Send + Sync {
|
||||
fn compact_revisions(user_id: &str, object_id: &str, revisions: Vec<Revision>) -> FlowyResult<Revision>;
|
||||
pub trait RevisionCompactor: Send + Sync {
|
||||
fn compact(&self, user_id: &str, object_id: &str, mut revisions: Vec<Revision>) -> FlowyResult<Revision> {
|
||||
if revisions.is_empty() {
|
||||
return Err(FlowyError::internal().context("Can't compact the empty folder's revisions"));
|
||||
}
|
||||
|
||||
if revisions.len() == 1 {
|
||||
return Ok(revisions.pop().unwrap());
|
||||
}
|
||||
|
||||
let first_revision = revisions.first().unwrap();
|
||||
let last_revision = revisions.last().unwrap();
|
||||
|
||||
let (base_rev_id, rev_id) = first_revision.pair_rev_id();
|
||||
let md5 = last_revision.md5.clone();
|
||||
let delta_data = self.bytes_from_revisions(revisions)?;
|
||||
Ok(Revision::new(object_id, base_rev_id, rev_id, delta_data, user_id, md5))
|
||||
}
|
||||
|
||||
fn bytes_from_revisions(&self, revisions: Vec<Revision>) -> FlowyResult<Bytes>;
|
||||
}
|
||||
|
||||
pub struct RevisionManager {
|
||||
@ -48,10 +68,9 @@ impl RevisionManager {
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn load<B, C>(&mut self, cloud: Arc<dyn RevisionCloudService>) -> FlowyResult<B::Output>
|
||||
pub async fn load<B>(&mut self, cloud: Arc<dyn RevisionCloudService>) -> FlowyResult<B::Output>
|
||||
where
|
||||
B: RevisionObjectBuilder,
|
||||
C: RevisionCompact,
|
||||
{
|
||||
let (revisions, rev_id) = RevisionLoader {
|
||||
object_id: self.object_id.clone(),
|
||||
@ -84,15 +103,16 @@ impl RevisionManager {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(self, revision))]
|
||||
pub async fn add_local_revision<C>(&self, revision: &Revision) -> Result<(), FlowyError>
|
||||
where
|
||||
C: RevisionCompact,
|
||||
{
|
||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||
pub async fn add_local_revision<'a>(
|
||||
&'a self,
|
||||
revision: &Revision,
|
||||
compactor: Box<dyn RevisionCompactor + 'a>,
|
||||
) -> Result<(), FlowyError> {
|
||||
if revision.delta_data.is_empty() {
|
||||
return Err(FlowyError::internal().context("Delta data should be empty"));
|
||||
}
|
||||
let rev_id = self.rev_persistence.add_sync_revision::<C>(revision).await?;
|
||||
let rev_id = self.rev_persistence.add_sync_revision(revision, compactor).await?;
|
||||
self.rev_id_counter.set(rev_id);
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
use crate::cache::{
|
||||
disk::{RevisionChangeset, RevisionDiskCache, SQLiteTextBlockRevisionPersistence},
|
||||
memory::{RevisionMemoryCache, RevisionMemoryCacheDelegate},
|
||||
memory::RevisionMemoryCacheDelegate,
|
||||
};
|
||||
use crate::disk::{RevisionRecord, RevisionState};
|
||||
use crate::RevisionCompact;
|
||||
use crate::memory::RevisionMemoryCache;
|
||||
use crate::RevisionCompactor;
|
||||
use flowy_collaboration::entities::revision::{Revision, RevisionRange};
|
||||
use flowy_database::ConnectionPool;
|
||||
use flowy_error::{internal_error, FlowyError, FlowyResult};
|
||||
@ -21,13 +22,17 @@ pub struct RevisionPersistence {
|
||||
memory_cache: Arc<RevisionMemoryCache>,
|
||||
sync_seq: RwLock<RevisionSyncSequence>,
|
||||
}
|
||||
|
||||
impl RevisionPersistence {
|
||||
pub fn new(user_id: &str, object_id: &str, pool: Arc<ConnectionPool>) -> RevisionPersistence {
|
||||
let disk_cache = Arc::new(SQLiteTextBlockRevisionPersistence::new(user_id, pool));
|
||||
let memory_cache = Arc::new(RevisionMemoryCache::new(object_id, Arc::new(disk_cache.clone())));
|
||||
pub fn new(
|
||||
user_id: &str,
|
||||
object_id: &str,
|
||||
disk_cache: Arc<dyn RevisionDiskCache<Error = FlowyError>>,
|
||||
) -> RevisionPersistence {
|
||||
let object_id = object_id.to_owned();
|
||||
let user_id = user_id.to_owned();
|
||||
let sync_seq = RwLock::new(RevisionSyncSequence::new());
|
||||
let memory_cache = Arc::new(RevisionMemoryCache::new(&object_id, Arc::new(disk_cache.clone())));
|
||||
Self {
|
||||
user_id,
|
||||
object_id,
|
||||
@ -54,11 +59,12 @@ impl RevisionPersistence {
|
||||
}
|
||||
|
||||
/// Save the revision to disk and append it to the end of the sync sequence.
|
||||
#[tracing::instrument(level = "trace", skip(self, revision), fields(rev_id, compact_range, object_id=%self.object_id), err)]
|
||||
pub(crate) async fn add_sync_revision<C>(&self, revision: &Revision) -> FlowyResult<i64>
|
||||
where
|
||||
C: RevisionCompact,
|
||||
{
|
||||
#[tracing::instrument(level = "trace", skip_all, fields(rev_id, compact_range, object_id=%self.object_id), err)]
|
||||
pub(crate) async fn add_sync_revision<'a>(
|
||||
&'a self,
|
||||
revision: &'a Revision,
|
||||
compactor: Box<dyn RevisionCompactor + 'a>,
|
||||
) -> FlowyResult<i64> {
|
||||
let result = self.sync_seq.read().await.compact();
|
||||
match result {
|
||||
None => {
|
||||
@ -78,7 +84,7 @@ impl RevisionPersistence {
|
||||
revisions.push(revision.clone());
|
||||
|
||||
// compact multiple revisions into one
|
||||
let compact_revision = C::compact_revisions(&self.user_id, &self.object_id, revisions)?;
|
||||
let compact_revision = compactor.compact(&self.user_id, &self.object_id, revisions)?;
|
||||
let rev_id = compact_revision.rev_id;
|
||||
tracing::Span::current().record("rev_id", &rev_id);
|
||||
|
||||
@ -215,17 +221,15 @@ pub fn mk_revision_disk_cache(
|
||||
Arc::new(SQLiteTextBlockRevisionPersistence::new(user_id, pool))
|
||||
}
|
||||
|
||||
impl RevisionMemoryCacheDelegate for Arc<SQLiteTextBlockRevisionPersistence> {
|
||||
#[tracing::instrument(level = "trace", skip(self, records), fields(checkpoint_result), err)]
|
||||
impl RevisionMemoryCacheDelegate for Arc<dyn RevisionDiskCache<Error = FlowyError>> {
|
||||
fn checkpoint_tick(&self, mut records: Vec<RevisionRecord>) -> FlowyResult<()> {
|
||||
let conn = &*self.pool.get().map_err(internal_error)?;
|
||||
records.retain(|record| record.write_to_disk);
|
||||
if !records.is_empty() {
|
||||
tracing::Span::current().record(
|
||||
"checkpoint_result",
|
||||
&format!("{} records were saved", records.len()).as_str(),
|
||||
);
|
||||
let _ = self.create_revision_records(records, conn)?;
|
||||
let _ = self.create_revision_records(records)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -1,28 +1,28 @@
|
||||
use crate::entities::revision::{md5, RepeatedRevision, Revision};
|
||||
use crate::errors::{internal_error, CollaborateError, CollaborateResult};
|
||||
use crate::util::{cal_diff, make_delta_from_revisions};
|
||||
use flowy_grid_data_model::entities::{BlockMeta, RowMeta, RowMetaChangeset, RowOrder};
|
||||
use flowy_grid_data_model::entities::{GridBlockMeta, RowMeta, RowMetaChangeset, RowOrder};
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type BlockMetaDelta = PlainTextDelta;
|
||||
pub type BlockDeltaBuilder = PlainTextDeltaBuilder;
|
||||
pub type GridBlockMetaDelta = PlainTextDelta;
|
||||
pub type GridBlockMetaDeltaBuilder = PlainTextDeltaBuilder;
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
pub struct BlockMetaPad {
|
||||
pub struct GridBlockMetaPad {
|
||||
block_id: String,
|
||||
rows: Vec<Arc<RowMeta>>,
|
||||
|
||||
#[serde(skip)]
|
||||
pub(crate) delta: BlockMetaDelta,
|
||||
pub(crate) delta: GridBlockMetaDelta,
|
||||
}
|
||||
|
||||
impl BlockMetaPad {
|
||||
pub fn from_delta(delta: BlockMetaDelta) -> CollaborateResult<Self> {
|
||||
impl GridBlockMetaPad {
|
||||
pub fn from_delta(delta: GridBlockMetaDelta) -> CollaborateResult<Self> {
|
||||
let s = delta.to_str()?;
|
||||
let block_meta: BlockMeta = serde_json::from_str(&s).map_err(|e| {
|
||||
let block_meta: GridBlockMeta = serde_json::from_str(&s).map_err(|e| {
|
||||
CollaborateError::internal().context(format!("Deserialize delta to block meta failed: {}", e))
|
||||
})?;
|
||||
let block_id = block_meta.block_id;
|
||||
@ -31,25 +31,25 @@ impl BlockMetaPad {
|
||||
}
|
||||
|
||||
pub fn from_revisions(_grid_id: &str, revisions: Vec<Revision>) -> CollaborateResult<Self> {
|
||||
let block_delta: BlockMetaDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
let block_delta: GridBlockMetaDelta = make_delta_from_revisions::<PlainTextAttributes>(revisions)?;
|
||||
Self::from_delta(block_delta)
|
||||
}
|
||||
|
||||
pub fn add_row(&mut self, row: RowMeta) -> CollaborateResult<Option<BlockMetaChange>> {
|
||||
pub fn add_row(&mut self, row: RowMeta) -> CollaborateResult<Option<GridBlockMetaChange>> {
|
||||
self.modify(|rows| {
|
||||
rows.push(Arc::new(row));
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete_rows(&mut self, row_ids: &[String]) -> CollaborateResult<Option<BlockMetaChange>> {
|
||||
pub fn delete_rows(&mut self, row_ids: &[String]) -> CollaborateResult<Option<GridBlockMetaChange>> {
|
||||
self.modify(|rows| {
|
||||
rows.retain(|row| !row_ids.contains(&row.id));
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult<Option<BlockMetaChange>> {
|
||||
pub fn update_row(&mut self, changeset: RowMetaChangeset) -> CollaborateResult<Option<GridBlockMetaChange>> {
|
||||
let row_id = changeset.row_id.clone();
|
||||
self.modify_row(&row_id, |row| {
|
||||
let mut is_changed = None;
|
||||
@ -74,7 +74,7 @@ impl BlockMetaPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn modify<F>(&mut self, f: F) -> CollaborateResult<Option<BlockMetaChange>>
|
||||
pub fn modify<F>(&mut self, f: F) -> CollaborateResult<Option<GridBlockMetaChange>>
|
||||
where
|
||||
F: for<'a> FnOnce(&'a mut Vec<Arc<RowMeta>>) -> CollaborateResult<Option<()>>,
|
||||
{
|
||||
@ -88,14 +88,14 @@ impl BlockMetaPad {
|
||||
None => Ok(None),
|
||||
Some(delta) => {
|
||||
self.delta = self.delta.compose(&delta)?;
|
||||
Ok(Some(BlockMetaChange { delta, md5: self.md5() }))
|
||||
Ok(Some(GridBlockMetaChange { delta, md5: self.md5() }))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn modify_row<F>(&mut self, row_id: &str, f: F) -> CollaborateResult<Option<BlockMetaChange>>
|
||||
fn modify_row<F>(&mut self, row_id: &str, f: F) -> CollaborateResult<Option<GridBlockMetaChange>>
|
||||
where
|
||||
F: FnOnce(&mut RowMeta) -> CollaborateResult<Option<()>>,
|
||||
{
|
||||
@ -123,39 +123,39 @@ impl BlockMetaPad {
|
||||
}
|
||||
}
|
||||
|
||||
fn json_from_grid(block_meta: &Arc<BlockMeta>) -> CollaborateResult<String> {
|
||||
fn json_from_grid(block_meta: &Arc<GridBlockMeta>) -> CollaborateResult<String> {
|
||||
let json = serde_json::to_string(block_meta)
|
||||
.map_err(|err| internal_error(format!("Serialize grid to json str failed. {:?}", err)))?;
|
||||
Ok(json)
|
||||
}
|
||||
|
||||
pub struct BlockMetaChange {
|
||||
pub delta: BlockMetaDelta,
|
||||
pub struct GridBlockMetaChange {
|
||||
pub delta: GridBlockMetaDelta,
|
||||
/// md5: the md5 of the grid after applying the change.
|
||||
pub md5: String,
|
||||
}
|
||||
|
||||
pub fn make_block_meta_delta(block_meta: &BlockMeta) -> BlockMetaDelta {
|
||||
pub fn make_block_meta_delta(block_meta: &GridBlockMeta) -> GridBlockMetaDelta {
|
||||
let json = serde_json::to_string(&block_meta).unwrap();
|
||||
PlainTextDeltaBuilder::new().insert(&json).build()
|
||||
}
|
||||
|
||||
pub fn make_block_meta_revisions(user_id: &str, block_meta: &BlockMeta) -> RepeatedRevision {
|
||||
pub fn make_block_meta_revisions(user_id: &str, block_meta: &GridBlockMeta) -> RepeatedRevision {
|
||||
let delta = make_block_meta_delta(block_meta);
|
||||
let bytes = delta.to_bytes();
|
||||
let revision = Revision::initial_revision(user_id, &block_meta.block_id, bytes);
|
||||
revision.into()
|
||||
}
|
||||
|
||||
impl std::default::Default for BlockMetaPad {
|
||||
impl std::default::Default for GridBlockMetaPad {
|
||||
fn default() -> Self {
|
||||
let block_meta = BlockMeta {
|
||||
let block_meta = GridBlockMeta {
|
||||
block_id: uuid(),
|
||||
rows: vec![],
|
||||
};
|
||||
|
||||
let delta = make_block_meta_delta(&block_meta);
|
||||
BlockMetaPad {
|
||||
GridBlockMetaPad {
|
||||
block_id: block_meta.block_id,
|
||||
rows: block_meta.rows.into_iter().map(Arc::new).collect::<Vec<_>>(),
|
||||
delta,
|
||||
@ -165,7 +165,7 @@ impl std::default::Default for BlockMetaPad {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::client_grid::{BlockMetaDelta, BlockMetaPad};
|
||||
use crate::client_grid::{GridBlockMetaDelta, GridMetaPad};
|
||||
use flowy_grid_data_model::entities::{RowMeta, RowMetaChangeset};
|
||||
use std::str::FromStr;
|
||||
|
||||
@ -241,8 +241,8 @@ mod tests {
|
||||
);
|
||||
}
|
||||
|
||||
fn test_pad() -> BlockMetaPad {
|
||||
let delta = BlockMetaDelta::from_delta_str(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap();
|
||||
BlockMetaPad::from_delta(delta).unwrap()
|
||||
fn test_pad() -> GridMetaPad {
|
||||
let delta = GridBlockMetaDelta::from_delta_str(r#"[{"insert":"{\"block_id\":\"1\",\"rows\":[]}"}]"#).unwrap();
|
||||
GridMetaPad::from_delta(delta).unwrap()
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
use crate::entities::revision::{md5, RepeatedRevision, Revision};
|
||||
use crate::errors::{internal_error, CollaborateError, CollaborateResult};
|
||||
use crate::util::{cal_diff, make_delta_from_revisions};
|
||||
use flowy_grid_data_model::entities::{Field, FieldOrder, Grid, GridMeta, RowMeta, RowOrder};
|
||||
use flowy_grid_data_model::entities::{
|
||||
Field, FieldChangeset, FieldOrder, Grid, GridBlock, GridBlockChangeset, GridMeta, RepeatedField,
|
||||
RepeatedFieldOrder, RowMeta, RowOrder,
|
||||
};
|
||||
use lib_infra::uuid;
|
||||
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub type GridDelta = PlainTextDelta;
|
||||
@ -31,13 +35,6 @@ impl GridMetaPad {
|
||||
Self::from_delta(grid_delta)
|
||||
}
|
||||
|
||||
pub fn create_row(&mut self, row: RowMeta) -> CollaborateResult<Option<GridChange>> {
|
||||
self.modify_grid(|grid| {
|
||||
// grid.rows.push(row);
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_field(&mut self, field: Field) -> CollaborateResult<Option<GridChange>> {
|
||||
self.modify_grid(|grid| {
|
||||
grid.fields.push(field);
|
||||
@ -45,13 +42,6 @@ impl GridMetaPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete_rows(&mut self, row_ids: &[String]) -> CollaborateResult<Option<GridChange>> {
|
||||
self.modify_grid(|grid| {
|
||||
// grid.rows.retain(|row| !row_ids.contains(&row.id));
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChange>> {
|
||||
self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
|
||||
None => Ok(None),
|
||||
@ -62,30 +52,93 @@ impl GridMetaPad {
|
||||
})
|
||||
}
|
||||
|
||||
pub fn md5(&self) -> String {
|
||||
md5(&self.delta.to_bytes())
|
||||
}
|
||||
|
||||
pub fn grid_data(&self) -> Grid {
|
||||
let field_orders = self
|
||||
pub fn get_fields(&self, field_orders: RepeatedFieldOrder) -> CollaborateResult<RepeatedField> {
|
||||
let field_by_field_id = self
|
||||
.grid_meta
|
||||
.fields
|
||||
.iter()
|
||||
.map(FieldOrder::from)
|
||||
.collect::<Vec<FieldOrder>>();
|
||||
.map(|field| (&field.id, field))
|
||||
.collect::<HashMap<&String, &Field>>();
|
||||
|
||||
// let row_orders = self
|
||||
// .grid_meta
|
||||
// .rows
|
||||
// .iter()
|
||||
// .map(RowOrder::from)
|
||||
// .collect::<Vec<RowOrder>>();
|
||||
let fields = field_orders
|
||||
.iter()
|
||||
.flat_map(|field_order| match field_by_field_id.get(&field_order.field_id) {
|
||||
None => {
|
||||
tracing::error!("Can't find the field with {}", field_order.field_id);
|
||||
None
|
||||
}
|
||||
Some(field) => Some((*field).clone()),
|
||||
})
|
||||
.collect::<Vec<Field>>();
|
||||
Ok(fields.into())
|
||||
}
|
||||
|
||||
Grid {
|
||||
id: "".to_string(),
|
||||
field_orders,
|
||||
row_orders: vec![],
|
||||
}
|
||||
pub fn update_field(&mut self, change: FieldChangeset) -> CollaborateResult<Option<GridChange>> {
|
||||
let field_id = change.field_id.clone();
|
||||
self.modify_field(&field_id, |field| {
|
||||
let mut is_changed = None;
|
||||
if let Some(name) = change.name {
|
||||
field.name = name;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(desc) = change.desc {
|
||||
field.desc = desc;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(field_type) = change.field_type {
|
||||
field.field_type = field_type;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(frozen) = change.frozen {
|
||||
field.frozen = frozen;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(visibility) = change.visibility {
|
||||
field.visibility = visibility;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(width) = change.width {
|
||||
field.width = width;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
if let Some(type_options) = change.type_options {
|
||||
field.type_options = type_options;
|
||||
is_changed = Some(())
|
||||
}
|
||||
|
||||
Ok(is_changed)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn create_block(&mut self, block: GridBlock) -> CollaborateResult<Option<GridChange>> {
|
||||
self.modify_grid(|grid| {
|
||||
grid.blocks.push(block);
|
||||
Ok(Some(()))
|
||||
})
|
||||
}
|
||||
|
||||
pub fn update_block(&mut self, change: GridBlockChangeset) -> CollaborateResult<Option<GridChange>> {
|
||||
let block_id = change.block_id.clone();
|
||||
self.modify_block(&block_id, |block| {
|
||||
let mut is_changed = None;
|
||||
|
||||
if let Some(row_count) = change.row_count {
|
||||
block.row_count = row_count;
|
||||
is_changed = Some(());
|
||||
}
|
||||
|
||||
Ok(is_changed)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn md5(&self) -> String {
|
||||
md5(&self.delta.to_bytes())
|
||||
}
|
||||
|
||||
pub fn delta_str(&self) -> String {
|
||||
@ -96,7 +149,7 @@ impl GridMetaPad {
|
||||
&self.grid_meta.fields
|
||||
}
|
||||
|
||||
pub fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridChange>>
|
||||
fn modify_grid<F>(&mut self, f: F) -> CollaborateResult<Option<GridChange>>
|
||||
where
|
||||
F: FnOnce(&mut GridMeta) -> CollaborateResult<Option<()>>,
|
||||
{
|
||||
@ -116,6 +169,32 @@ impl GridMetaPad {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn modify_block<F>(&mut self, block_id: &str, f: F) -> CollaborateResult<Option<GridChange>>
|
||||
where
|
||||
F: FnOnce(&mut GridBlock) -> CollaborateResult<Option<()>>,
|
||||
{
|
||||
self.modify_grid(|grid| match grid.blocks.iter().position(|block| block.id == block_id) {
|
||||
None => {
|
||||
tracing::warn!("[GridMetaPad]: Can't find any block with id: {}", block_id);
|
||||
Ok(None)
|
||||
}
|
||||
Some(index) => f(&mut grid.blocks[index]),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn modify_field<F>(&mut self, field_id: &str, f: F) -> CollaborateResult<Option<GridChange>>
|
||||
where
|
||||
F: FnOnce(&mut Field) -> CollaborateResult<Option<()>>,
|
||||
{
|
||||
self.modify_grid(|grid| match grid.fields.iter().position(|field| field.id == field_id) {
|
||||
None => {
|
||||
tracing::warn!("[GridMetaPad]: Can't find any field with id: {}", field_id);
|
||||
Ok(None)
|
||||
}
|
||||
Some(index) => f(&mut grid.fields[index]),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
fn json_from_grid(grid: &Arc<GridMeta>) -> CollaborateResult<String> {
|
||||
|
@ -2,9 +2,6 @@ use crate::entities::{Field, RowMeta};
|
||||
use flowy_derive::ProtoBuf;
|
||||
use std::collections::HashMap;
|
||||
|
||||
pub const DEFAULT_ROW_HEIGHT: i32 = 36;
|
||||
pub const DEFAULT_FIELD_WIDTH: i32 = 150;
|
||||
|
||||
#[derive(Debug, Clone, Default, ProtoBuf)]
|
||||
pub struct Grid {
|
||||
#[pb(index = 1)]
|
||||
|
@ -15,11 +15,11 @@ pub struct GridMeta {
|
||||
pub fields: Vec<Field>,
|
||||
|
||||
#[pb(index = 3)]
|
||||
pub blocks: Vec<Block>,
|
||||
pub blocks: Vec<GridBlock>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct Block {
|
||||
pub struct GridBlock {
|
||||
#[pb(index = 1)]
|
||||
pub id: String,
|
||||
|
||||
@ -30,8 +30,14 @@ pub struct Block {
|
||||
pub row_count: i32,
|
||||
}
|
||||
|
||||
pub struct GridBlockChangeset {
|
||||
pub block_id: String,
|
||||
pub start_row_index: Option<i32>,
|
||||
pub row_count: Option<i32>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize, ProtoBuf)]
|
||||
pub struct BlockMeta {
|
||||
pub struct GridBlockMeta {
|
||||
#[pb(index = 1)]
|
||||
pub block_id: String,
|
||||
|
||||
@ -81,6 +87,33 @@ impl Field {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Default, ProtoBuf)]
|
||||
pub struct FieldChangeset {
|
||||
#[pb(index = 1)]
|
||||
pub field_id: String,
|
||||
|
||||
#[pb(index = 2, one_of)]
|
||||
pub name: Option<String>,
|
||||
|
||||
#[pb(index = 3, one_of)]
|
||||
pub desc: Option<String>,
|
||||
|
||||
#[pb(index = 4, one_of)]
|
||||
pub field_type: Option<FieldType>,
|
||||
|
||||
#[pb(index = 5, one_of)]
|
||||
pub frozen: Option<bool>,
|
||||
|
||||
#[pb(index = 6, one_of)]
|
||||
pub visibility: Option<bool>,
|
||||
|
||||
#[pb(index = 7, one_of)]
|
||||
pub width: Option<i32>,
|
||||
|
||||
#[pb(index = 8, one_of)]
|
||||
pub type_options: Option<AnyData>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, ProtoBuf)]
|
||||
pub struct RepeatedField {
|
||||
#[pb(index = 1)]
|
||||
@ -191,7 +224,7 @@ pub struct RowMeta {
|
||||
}
|
||||
|
||||
impl RowMeta {
|
||||
pub fn new(id: &str, grid_id: &str, cells: Vec<CellMeta>) -> Self {
|
||||
pub fn new(id: &str, block_id: &str, cells: Vec<CellMeta>) -> Self {
|
||||
let cell_by_field_id = cells
|
||||
.into_iter()
|
||||
.map(|cell| (cell.id.clone(), cell))
|
||||
@ -199,7 +232,7 @@ impl RowMeta {
|
||||
|
||||
Self {
|
||||
id: id.to_owned(),
|
||||
block_id: grid_id.to_owned(),
|
||||
block_id: block_id.to_owned(),
|
||||
cell_by_field_id,
|
||||
height: DEFAULT_ROW_HEIGHT,
|
||||
visibility: true,
|
||||
|
@ -28,7 +28,7 @@ pub struct GridMeta {
|
||||
// message fields
|
||||
pub grid_id: ::std::string::String,
|
||||
pub fields: ::protobuf::RepeatedField<Field>,
|
||||
pub blocks: ::protobuf::RepeatedField<Block>,
|
||||
pub blocks: ::protobuf::RepeatedField<GridBlock>,
|
||||
// special fields
|
||||
pub unknown_fields: ::protobuf::UnknownFields,
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
@ -96,10 +96,10 @@ impl GridMeta {
|
||||
::std::mem::replace(&mut self.fields, ::protobuf::RepeatedField::new())
|
||||
}
|
||||
|
||||
// repeated .Block blocks = 3;
|
||||
// repeated .GridBlock blocks = 3;
|
||||
|
||||
|
||||
pub fn get_blocks(&self) -> &[Block] {
|
||||
pub fn get_blocks(&self) -> &[GridBlock] {
|
||||
&self.blocks
|
||||
}
|
||||
pub fn clear_blocks(&mut self) {
|
||||
@ -107,17 +107,17 @@ impl GridMeta {
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_blocks(&mut self, v: ::protobuf::RepeatedField<Block>) {
|
||||
pub fn set_blocks(&mut self, v: ::protobuf::RepeatedField<GridBlock>) {
|
||||
self.blocks = v;
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
pub fn mut_blocks(&mut self) -> &mut ::protobuf::RepeatedField<Block> {
|
||||
pub fn mut_blocks(&mut self) -> &mut ::protobuf::RepeatedField<GridBlock> {
|
||||
&mut self.blocks
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_blocks(&mut self) -> ::protobuf::RepeatedField<Block> {
|
||||
pub fn take_blocks(&mut self) -> ::protobuf::RepeatedField<GridBlock> {
|
||||
::std::mem::replace(&mut self.blocks, ::protobuf::RepeatedField::new())
|
||||
}
|
||||
}
|
||||
@ -240,7 +240,7 @@ impl ::protobuf::Message for GridMeta {
|
||||
|m: &GridMeta| { &m.fields },
|
||||
|m: &mut GridMeta| { &mut m.fields },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<Block>>(
|
||||
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<GridBlock>>(
|
||||
"blocks",
|
||||
|m: &GridMeta| { &m.blocks },
|
||||
|m: &mut GridMeta| { &mut m.blocks },
|
||||
@ -281,7 +281,7 @@ impl ::protobuf::reflect::ProtobufValue for GridMeta {
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct Block {
|
||||
pub struct GridBlock {
|
||||
// message fields
|
||||
pub id: ::std::string::String,
|
||||
pub start_row_index: i32,
|
||||
@ -291,14 +291,14 @@ pub struct Block {
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a Block {
|
||||
fn default() -> &'a Block {
|
||||
<Block as ::protobuf::Message>::default_instance()
|
||||
impl<'a> ::std::default::Default for &'a GridBlock {
|
||||
fn default() -> &'a GridBlock {
|
||||
<GridBlock as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl Block {
|
||||
pub fn new() -> Block {
|
||||
impl GridBlock {
|
||||
pub fn new() -> GridBlock {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
@ -359,7 +359,7 @@ impl Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for Block {
|
||||
impl ::protobuf::Message for GridBlock {
|
||||
fn is_initialized(&self) -> bool {
|
||||
true
|
||||
}
|
||||
@ -451,8 +451,8 @@ impl ::protobuf::Message for Block {
|
||||
Self::descriptor_static()
|
||||
}
|
||||
|
||||
fn new() -> Block {
|
||||
Block::new()
|
||||
fn new() -> GridBlock {
|
||||
GridBlock::new()
|
||||
}
|
||||
|
||||
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
@ -461,34 +461,34 @@ impl ::protobuf::Message for Block {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
|
||||
"id",
|
||||
|m: &Block| { &m.id },
|
||||
|m: &mut Block| { &mut m.id },
|
||||
|m: &GridBlock| { &m.id },
|
||||
|m: &mut GridBlock| { &mut m.id },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
|
||||
"start_row_index",
|
||||
|m: &Block| { &m.start_row_index },
|
||||
|m: &mut Block| { &mut m.start_row_index },
|
||||
|m: &GridBlock| { &m.start_row_index },
|
||||
|m: &mut GridBlock| { &mut m.start_row_index },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
|
||||
"row_count",
|
||||
|m: &Block| { &m.row_count },
|
||||
|m: &mut Block| { &mut m.row_count },
|
||||
|m: &GridBlock| { &m.row_count },
|
||||
|m: &mut GridBlock| { &mut m.row_count },
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<Block>(
|
||||
"Block",
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<GridBlock>(
|
||||
"GridBlock",
|
||||
fields,
|
||||
file_descriptor_proto()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static Block {
|
||||
static instance: ::protobuf::rt::LazyV2<Block> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(Block::new)
|
||||
fn default_instance() -> &'static GridBlock {
|
||||
static instance: ::protobuf::rt::LazyV2<GridBlock> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(GridBlock::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Clear for Block {
|
||||
impl ::protobuf::Clear for GridBlock {
|
||||
fn clear(&mut self) {
|
||||
self.id.clear();
|
||||
self.start_row_index = 0;
|
||||
@ -497,20 +497,20 @@ impl ::protobuf::Clear for Block {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for Block {
|
||||
impl ::std::fmt::Debug for GridBlock {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for Block {
|
||||
impl ::protobuf::reflect::ProtobufValue for GridBlock {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct BlockMeta {
|
||||
pub struct GridBlockMeta {
|
||||
// message fields
|
||||
pub block_id: ::std::string::String,
|
||||
pub rows: ::protobuf::RepeatedField<RowMeta>,
|
||||
@ -519,14 +519,14 @@ pub struct BlockMeta {
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a BlockMeta {
|
||||
fn default() -> &'a BlockMeta {
|
||||
<BlockMeta as ::protobuf::Message>::default_instance()
|
||||
impl<'a> ::std::default::Default for &'a GridBlockMeta {
|
||||
fn default() -> &'a GridBlockMeta {
|
||||
<GridBlockMeta as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
impl BlockMeta {
|
||||
pub fn new() -> BlockMeta {
|
||||
impl GridBlockMeta {
|
||||
pub fn new() -> GridBlockMeta {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
@ -582,7 +582,7 @@ impl BlockMeta {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for BlockMeta {
|
||||
impl ::protobuf::Message for GridBlockMeta {
|
||||
fn is_initialized(&self) -> bool {
|
||||
for v in &self.rows {
|
||||
if !v.is_initialized() {
|
||||
@ -665,8 +665,8 @@ impl ::protobuf::Message for BlockMeta {
|
||||
Self::descriptor_static()
|
||||
}
|
||||
|
||||
fn new() -> BlockMeta {
|
||||
BlockMeta::new()
|
||||
fn new() -> GridBlockMeta {
|
||||
GridBlockMeta::new()
|
||||
}
|
||||
|
||||
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
@ -675,29 +675,29 @@ impl ::protobuf::Message for BlockMeta {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
|
||||
"block_id",
|
||||
|m: &BlockMeta| { &m.block_id },
|
||||
|m: &mut BlockMeta| { &mut m.block_id },
|
||||
|m: &GridBlockMeta| { &m.block_id },
|
||||
|m: &mut GridBlockMeta| { &mut m.block_id },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_repeated_field_accessor::<_, ::protobuf::types::ProtobufTypeMessage<RowMeta>>(
|
||||
"rows",
|
||||
|m: &BlockMeta| { &m.rows },
|
||||
|m: &mut BlockMeta| { &mut m.rows },
|
||||
|m: &GridBlockMeta| { &m.rows },
|
||||
|m: &mut GridBlockMeta| { &mut m.rows },
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<BlockMeta>(
|
||||
"BlockMeta",
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<GridBlockMeta>(
|
||||
"GridBlockMeta",
|
||||
fields,
|
||||
file_descriptor_proto()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static BlockMeta {
|
||||
static instance: ::protobuf::rt::LazyV2<BlockMeta> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(BlockMeta::new)
|
||||
fn default_instance() -> &'static GridBlockMeta {
|
||||
static instance: ::protobuf::rt::LazyV2<GridBlockMeta> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(GridBlockMeta::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Clear for BlockMeta {
|
||||
impl ::protobuf::Clear for GridBlockMeta {
|
||||
fn clear(&mut self) {
|
||||
self.block_id.clear();
|
||||
self.rows.clear();
|
||||
@ -705,13 +705,13 @@ impl ::protobuf::Clear for BlockMeta {
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for BlockMeta {
|
||||
impl ::std::fmt::Debug for GridBlockMeta {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for BlockMeta {
|
||||
impl ::protobuf::reflect::ProtobufValue for GridBlockMeta {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||
}
|
||||
@ -1319,6 +1319,645 @@ impl ::protobuf::reflect::ProtobufValue for RepeatedField {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct FieldChangeset {
|
||||
// message fields
|
||||
pub field_id: ::std::string::String,
|
||||
// message oneof groups
|
||||
pub one_of_name: ::std::option::Option<FieldChangeset_oneof_one_of_name>,
|
||||
pub one_of_desc: ::std::option::Option<FieldChangeset_oneof_one_of_desc>,
|
||||
pub one_of_field_type: ::std::option::Option<FieldChangeset_oneof_one_of_field_type>,
|
||||
pub one_of_frozen: ::std::option::Option<FieldChangeset_oneof_one_of_frozen>,
|
||||
pub one_of_visibility: ::std::option::Option<FieldChangeset_oneof_one_of_visibility>,
|
||||
pub one_of_width: ::std::option::Option<FieldChangeset_oneof_one_of_width>,
|
||||
pub one_of_type_options: ::std::option::Option<FieldChangeset_oneof_one_of_type_options>,
|
||||
// special fields
|
||||
pub unknown_fields: ::protobuf::UnknownFields,
|
||||
pub cached_size: ::protobuf::CachedSize,
|
||||
}
|
||||
|
||||
impl<'a> ::std::default::Default for &'a FieldChangeset {
|
||||
fn default() -> &'a FieldChangeset {
|
||||
<FieldChangeset as ::protobuf::Message>::default_instance()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_name {
|
||||
name(::std::string::String),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_desc {
|
||||
desc(::std::string::String),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_field_type {
|
||||
field_type(FieldType),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_frozen {
|
||||
frozen(bool),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_visibility {
|
||||
visibility(bool),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_width {
|
||||
width(i32),
|
||||
}
|
||||
|
||||
#[derive(Clone,PartialEq,Debug)]
|
||||
pub enum FieldChangeset_oneof_one_of_type_options {
|
||||
type_options(AnyData),
|
||||
}
|
||||
|
||||
impl FieldChangeset {
|
||||
pub fn new() -> FieldChangeset {
|
||||
::std::default::Default::default()
|
||||
}
|
||||
|
||||
// string field_id = 1;
|
||||
|
||||
|
||||
pub fn get_field_id(&self) -> &str {
|
||||
&self.field_id
|
||||
}
|
||||
pub fn clear_field_id(&mut self) {
|
||||
self.field_id.clear();
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_field_id(&mut self, v: ::std::string::String) {
|
||||
self.field_id = v;
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
// If field is not initialized, it is initialized with default value first.
|
||||
pub fn mut_field_id(&mut self) -> &mut ::std::string::String {
|
||||
&mut self.field_id
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_field_id(&mut self) -> ::std::string::String {
|
||||
::std::mem::replace(&mut self.field_id, ::std::string::String::new())
|
||||
}
|
||||
|
||||
// string name = 2;
|
||||
|
||||
|
||||
pub fn get_name(&self) -> &str {
|
||||
match self.one_of_name {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref v)) => v,
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
pub fn clear_name(&mut self) {
|
||||
self.one_of_name = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_name(&self) -> bool {
|
||||
match self.one_of_name {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_name(&mut self, v: ::std::string::String) {
|
||||
self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v))
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
pub fn mut_name(&mut self) -> &mut ::std::string::String {
|
||||
if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(_)) = self.one_of_name {
|
||||
} else {
|
||||
self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(::std::string::String::new()));
|
||||
}
|
||||
match self.one_of_name {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(ref mut v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_name(&mut self) -> ::std::string::String {
|
||||
if self.has_name() {
|
||||
match self.one_of_name.take() {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
} else {
|
||||
::std::string::String::new()
|
||||
}
|
||||
}
|
||||
|
||||
// string desc = 3;
|
||||
|
||||
|
||||
pub fn get_desc(&self) -> &str {
|
||||
match self.one_of_desc {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref v)) => v,
|
||||
_ => "",
|
||||
}
|
||||
}
|
||||
pub fn clear_desc(&mut self) {
|
||||
self.one_of_desc = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_desc(&self) -> bool {
|
||||
match self.one_of_desc {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_desc(&mut self, v: ::std::string::String) {
|
||||
self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v))
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
pub fn mut_desc(&mut self) -> &mut ::std::string::String {
|
||||
if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(_)) = self.one_of_desc {
|
||||
} else {
|
||||
self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(::std::string::String::new()));
|
||||
}
|
||||
match self.one_of_desc {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(ref mut v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_desc(&mut self) -> ::std::string::String {
|
||||
if self.has_desc() {
|
||||
match self.one_of_desc.take() {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
} else {
|
||||
::std::string::String::new()
|
||||
}
|
||||
}
|
||||
|
||||
// .FieldType field_type = 4;
|
||||
|
||||
|
||||
pub fn get_field_type(&self) -> FieldType {
|
||||
match self.one_of_field_type {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v)) => v,
|
||||
_ => FieldType::RichText,
|
||||
}
|
||||
}
|
||||
pub fn clear_field_type(&mut self) {
|
||||
self.one_of_field_type = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_field_type(&self) -> bool {
|
||||
match self.one_of_field_type {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_field_type(&mut self, v: FieldType) {
|
||||
self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(v))
|
||||
}
|
||||
|
||||
// bool frozen = 5;
|
||||
|
||||
|
||||
pub fn get_frozen(&self) -> bool {
|
||||
match self.one_of_frozen {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v)) => v,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn clear_frozen(&mut self) {
|
||||
self.one_of_frozen = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_frozen(&self) -> bool {
|
||||
match self.one_of_frozen {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_frozen(&mut self, v: bool) {
|
||||
self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(v))
|
||||
}
|
||||
|
||||
// bool visibility = 6;
|
||||
|
||||
|
||||
pub fn get_visibility(&self) -> bool {
|
||||
match self.one_of_visibility {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v)) => v,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
pub fn clear_visibility(&mut self) {
|
||||
self.one_of_visibility = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_visibility(&self) -> bool {
|
||||
match self.one_of_visibility {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_visibility(&mut self, v: bool) {
|
||||
self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(v))
|
||||
}
|
||||
|
||||
// int32 width = 7;
|
||||
|
||||
|
||||
pub fn get_width(&self) -> i32 {
|
||||
match self.one_of_width {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v)) => v,
|
||||
_ => 0,
|
||||
}
|
||||
}
|
||||
pub fn clear_width(&mut self) {
|
||||
self.one_of_width = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_width(&self) -> bool {
|
||||
match self.one_of_width {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_width(&mut self, v: i32) {
|
||||
self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(v))
|
||||
}
|
||||
|
||||
// .AnyData type_options = 8;
|
||||
|
||||
|
||||
pub fn get_type_options(&self) -> &AnyData {
|
||||
match self.one_of_type_options {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref v)) => v,
|
||||
_ => <AnyData as ::protobuf::Message>::default_instance(),
|
||||
}
|
||||
}
|
||||
pub fn clear_type_options(&mut self) {
|
||||
self.one_of_type_options = ::std::option::Option::None;
|
||||
}
|
||||
|
||||
pub fn has_type_options(&self) -> bool {
|
||||
match self.one_of_type_options {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(..)) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
// Param is passed by value, moved
|
||||
pub fn set_type_options(&mut self, v: AnyData) {
|
||||
self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v))
|
||||
}
|
||||
|
||||
// Mutable pointer to the field.
|
||||
pub fn mut_type_options(&mut self) -> &mut AnyData {
|
||||
if let ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(_)) = self.one_of_type_options {
|
||||
} else {
|
||||
self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(AnyData::new()));
|
||||
}
|
||||
match self.one_of_type_options {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(ref mut v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
}
|
||||
|
||||
// Take field
|
||||
pub fn take_type_options(&mut self) -> AnyData {
|
||||
if self.has_type_options() {
|
||||
match self.one_of_type_options.take() {
|
||||
::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(v)) => v,
|
||||
_ => panic!(),
|
||||
}
|
||||
} else {
|
||||
AnyData::new()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Message for FieldChangeset {
|
||||
fn is_initialized(&self) -> bool {
|
||||
if let Some(FieldChangeset_oneof_one_of_type_options::type_options(ref v)) = self.one_of_type_options {
|
||||
if !v.is_initialized() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
true
|
||||
}
|
||||
|
||||
fn merge_from(&mut self, is: &mut ::protobuf::CodedInputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||
while !is.eof()? {
|
||||
let (field_number, wire_type) = is.read_tag_unpack()?;
|
||||
match field_number {
|
||||
1 => {
|
||||
::protobuf::rt::read_singular_proto3_string_into(wire_type, is, &mut self.field_id)?;
|
||||
},
|
||||
2 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_name = ::std::option::Option::Some(FieldChangeset_oneof_one_of_name::name(is.read_string()?));
|
||||
},
|
||||
3 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_desc = ::std::option::Option::Some(FieldChangeset_oneof_one_of_desc::desc(is.read_string()?));
|
||||
},
|
||||
4 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_field_type = ::std::option::Option::Some(FieldChangeset_oneof_one_of_field_type::field_type(is.read_enum()?));
|
||||
},
|
||||
5 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_frozen = ::std::option::Option::Some(FieldChangeset_oneof_one_of_frozen::frozen(is.read_bool()?));
|
||||
},
|
||||
6 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_visibility = ::std::option::Option::Some(FieldChangeset_oneof_one_of_visibility::visibility(is.read_bool()?));
|
||||
},
|
||||
7 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_width = ::std::option::Option::Some(FieldChangeset_oneof_one_of_width::width(is.read_int32()?));
|
||||
},
|
||||
8 => {
|
||||
if wire_type != ::protobuf::wire_format::WireTypeLengthDelimited {
|
||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||
}
|
||||
self.one_of_type_options = ::std::option::Option::Some(FieldChangeset_oneof_one_of_type_options::type_options(is.read_message()?));
|
||||
},
|
||||
_ => {
|
||||
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||
},
|
||||
};
|
||||
}
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
// Compute sizes of nested messages
|
||||
#[allow(unused_variables)]
|
||||
fn compute_size(&self) -> u32 {
|
||||
let mut my_size = 0;
|
||||
if !self.field_id.is_empty() {
|
||||
my_size += ::protobuf::rt::string_size(1, &self.field_id);
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_name {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_name::name(ref v) => {
|
||||
my_size += ::protobuf::rt::string_size(2, &v);
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_desc {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_desc::desc(ref v) => {
|
||||
my_size += ::protobuf::rt::string_size(3, &v);
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_field_type {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_field_type::field_type(v) => {
|
||||
my_size += ::protobuf::rt::enum_size(4, v);
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_frozen {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_frozen::frozen(v) => {
|
||||
my_size += 2;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_visibility {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_visibility::visibility(v) => {
|
||||
my_size += 2;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_width {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_width::width(v) => {
|
||||
my_size += ::protobuf::rt::value_size(7, v, ::protobuf::wire_format::WireTypeVarint);
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_type_options {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_type_options::type_options(ref v) => {
|
||||
let len = v.compute_size();
|
||||
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
|
||||
},
|
||||
};
|
||||
}
|
||||
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||
self.cached_size.set(my_size);
|
||||
my_size
|
||||
}
|
||||
|
||||
fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
|
||||
if !self.field_id.is_empty() {
|
||||
os.write_string(1, &self.field_id)?;
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_name {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_name::name(ref v) => {
|
||||
os.write_string(2, v)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_desc {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_desc::desc(ref v) => {
|
||||
os.write_string(3, v)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_field_type {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_field_type::field_type(v) => {
|
||||
os.write_enum(4, ::protobuf::ProtobufEnum::value(&v))?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_frozen {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_frozen::frozen(v) => {
|
||||
os.write_bool(5, v)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_visibility {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_visibility::visibility(v) => {
|
||||
os.write_bool(6, v)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_width {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_width::width(v) => {
|
||||
os.write_int32(7, v)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
if let ::std::option::Option::Some(ref v) = self.one_of_type_options {
|
||||
match v {
|
||||
&FieldChangeset_oneof_one_of_type_options::type_options(ref v) => {
|
||||
os.write_tag(8, ::protobuf::wire_format::WireTypeLengthDelimited)?;
|
||||
os.write_raw_varint32(v.get_cached_size())?;
|
||||
v.write_to_with_cached_sizes(os)?;
|
||||
},
|
||||
};
|
||||
}
|
||||
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||
::std::result::Result::Ok(())
|
||||
}
|
||||
|
||||
fn get_cached_size(&self) -> u32 {
|
||||
self.cached_size.get()
|
||||
}
|
||||
|
||||
fn get_unknown_fields(&self) -> &::protobuf::UnknownFields {
|
||||
&self.unknown_fields
|
||||
}
|
||||
|
||||
fn mut_unknown_fields(&mut self) -> &mut ::protobuf::UnknownFields {
|
||||
&mut self.unknown_fields
|
||||
}
|
||||
|
||||
fn as_any(&self) -> &dyn (::std::any::Any) {
|
||||
self as &dyn (::std::any::Any)
|
||||
}
|
||||
fn as_any_mut(&mut self) -> &mut dyn (::std::any::Any) {
|
||||
self as &mut dyn (::std::any::Any)
|
||||
}
|
||||
fn into_any(self: ::std::boxed::Box<Self>) -> ::std::boxed::Box<dyn (::std::any::Any)> {
|
||||
self
|
||||
}
|
||||
|
||||
fn descriptor(&self) -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
Self::descriptor_static()
|
||||
}
|
||||
|
||||
fn new() -> FieldChangeset {
|
||||
FieldChangeset::new()
|
||||
}
|
||||
|
||||
fn descriptor_static() -> &'static ::protobuf::reflect::MessageDescriptor {
|
||||
static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::MessageDescriptor> = ::protobuf::rt::LazyV2::INIT;
|
||||
descriptor.get(|| {
|
||||
let mut fields = ::std::vec::Vec::new();
|
||||
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeString>(
|
||||
"field_id",
|
||||
|m: &FieldChangeset| { &m.field_id },
|
||||
|m: &mut FieldChangeset| { &mut m.field_id },
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
|
||||
"name",
|
||||
FieldChangeset::has_name,
|
||||
FieldChangeset::get_name,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_string_accessor::<_>(
|
||||
"desc",
|
||||
FieldChangeset::has_desc,
|
||||
FieldChangeset::get_desc,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_enum_accessor::<_, FieldType>(
|
||||
"field_type",
|
||||
FieldChangeset::has_field_type,
|
||||
FieldChangeset::get_field_type,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
|
||||
"frozen",
|
||||
FieldChangeset::has_frozen,
|
||||
FieldChangeset::get_frozen,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_bool_accessor::<_>(
|
||||
"visibility",
|
||||
FieldChangeset::has_visibility,
|
||||
FieldChangeset::get_visibility,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_i32_accessor::<_>(
|
||||
"width",
|
||||
FieldChangeset::has_width,
|
||||
FieldChangeset::get_width,
|
||||
));
|
||||
fields.push(::protobuf::reflect::accessor::make_singular_message_accessor::<_, AnyData>(
|
||||
"type_options",
|
||||
FieldChangeset::has_type_options,
|
||||
FieldChangeset::get_type_options,
|
||||
));
|
||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<FieldChangeset>(
|
||||
"FieldChangeset",
|
||||
fields,
|
||||
file_descriptor_proto()
|
||||
)
|
||||
})
|
||||
}
|
||||
|
||||
fn default_instance() -> &'static FieldChangeset {
|
||||
static instance: ::protobuf::rt::LazyV2<FieldChangeset> = ::protobuf::rt::LazyV2::INIT;
|
||||
instance.get(FieldChangeset::new)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::Clear for FieldChangeset {
|
||||
fn clear(&mut self) {
|
||||
self.field_id.clear();
|
||||
self.one_of_name = ::std::option::Option::None;
|
||||
self.one_of_desc = ::std::option::Option::None;
|
||||
self.one_of_field_type = ::std::option::Option::None;
|
||||
self.one_of_frozen = ::std::option::Option::None;
|
||||
self.one_of_visibility = ::std::option::Option::None;
|
||||
self.one_of_width = ::std::option::Option::None;
|
||||
self.one_of_type_options = ::std::option::Option::None;
|
||||
self.unknown_fields.clear();
|
||||
}
|
||||
}
|
||||
|
||||
impl ::std::fmt::Debug for FieldChangeset {
|
||||
fn fmt(&self, f: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
|
||||
::protobuf::text_format::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl ::protobuf::reflect::ProtobufValue for FieldChangeset {
|
||||
fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
|
||||
::protobuf::reflect::ReflectValueRef::Message(self)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq,Clone,Default)]
|
||||
pub struct AnyData {
|
||||
// message fields
|
||||
@ -2537,43 +3176,53 @@ impl ::protobuf::reflect::ProtobufValue for FieldType {
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\nmeta.proto\"c\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||
\n\nmeta.proto\"g\n\x08GridMeta\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||
\x06gridId\x12\x1e\n\x06fields\x18\x02\x20\x03(\x0b2\x06.FieldR\x06field\
|
||||
s\x12\x1e\n\x06blocks\x18\x03\x20\x03(\x0b2\x06.BlockR\x06blocks\"\\\n\
|
||||
\x05Block\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12&\n\x0fstart_row_\
|
||||
index\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\x1b\n\trow_count\x18\x03\
|
||||
\x20\x01(\x05R\x08rowCount\"D\n\tBlockMeta\x12\x19\n\x08block_id\x18\x01\
|
||||
\x20\x01(\tR\x07blockId\x12\x1c\n\x04rows\x18\x02\x20\x03(\x0b2\x08.RowM\
|
||||
etaR\x04rows\"\xe5\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\
|
||||
\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\
|
||||
s\x12\"\n\x06blocks\x18\x03\x20\x03(\x0b2\n.GridBlockR\x06blocks\"`\n\tG\
|
||||
ridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12&\n\x0fstart_row_i\
|
||||
ndex\x18\x02\x20\x01(\x05R\rstartRowIndex\x12\x1b\n\trow_count\x18\x03\
|
||||
\x20\x01(\x05R\x08rowCount\"H\n\rGridBlockMeta\x12\x19\n\x08block_id\x18\
|
||||
\x01\x20\x01(\tR\x07blockId\x12\x1c\n\x04rows\x18\x02\x20\x03(\x0b2\x08.\
|
||||
RowMetaR\x04rows\"\xe5\x01\n\x05Field\x12\x0e\n\x02id\x18\x01\x20\x01(\t\
|
||||
R\x02id\x12\x12\n\x04name\x18\x02\x20\x01(\tR\x04name\x12\x12\n\x04desc\
|
||||
\x18\x03\x20\x01(\tR\x04desc\x12)\n\nfield_type\x18\x04\x20\x01(\x0e2\n.\
|
||||
FieldTypeR\tfieldType\x12\x16\n\x06frozen\x18\x05\x20\x01(\x08R\x06froze\
|
||||
n\x12\x1e\n\nvisibility\x18\x06\x20\x01(\x08R\nvisibility\x12\x14\n\x05w\
|
||||
idth\x18\x07\x20\x01(\x05R\x05width\x12+\n\x0ctype_options\x18\x08\x20\
|
||||
\x01(\x0b2\x08.AnyDataR\x0btypeOptions\"-\n\rRepeatedField\x12\x1c\n\x05\
|
||||
items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"8\n\x07AnyData\x12\x17\
|
||||
\n\x07type_id\x18\x01\x20\x01(\tR\x06typeId\x12\x14\n\x05value\x18\x02\
|
||||
\x20\x01(\x0cR\x05value\"\xff\x01\n\x07RowMeta\x12\x0e\n\x02id\x18\x01\
|
||||
\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\
|
||||
\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\x0b2\x1b.RowMeta.CellByFiel\
|
||||
dIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x04\x20\x01(\x05R\x06he\
|
||||
ight\x12\x1e\n\nvisibility\x18\x05\x20\x01(\x08R\nvisibility\x1aK\n\x12C\
|
||||
ellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\
|
||||
\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\x028\x01\"\xa7\x02\
|
||||
\n\x10RowMetaChangeset\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\
|
||||
\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\0R\x06height\x12\x20\n\nvisib\
|
||||
ility\x18\x03\x20\x01(\x08H\x01R\nvisibility\x12M\n\x10cell_by_field_id\
|
||||
\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.CellByFieldIdEntryR\rcellByFiel\
|
||||
dId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\
|
||||
\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\x05value:\
|
||||
\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one_of_visibility\"\x82\x01\n\
|
||||
\x08CellMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x15\n\x06row_\
|
||||
id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\t\
|
||||
R\x07fieldId\x12\x1c\n\x04data\x18\x04\x20\x01(\x0b2\x08.AnyDataR\x04dat\
|
||||
a\x12\x16\n\x06height\x18\x05\x20\x01(\x05R\x06height*d\n\tFieldType\x12\
|
||||
\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\
|
||||
\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\
|
||||
\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
|
||||
items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"\x87\x03\n\x0eFieldChan\
|
||||
geset\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x14\n\x04\
|
||||
name\x18\x02\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\x03\x20\x01(\t\
|
||||
H\x01R\x04desc\x12+\n\nfield_type\x18\x04\x20\x01(\x0e2\n.FieldTypeH\x02\
|
||||
R\tfieldType\x12\x18\n\x06frozen\x18\x05\x20\x01(\x08H\x03R\x06frozen\
|
||||
\x12\x20\n\nvisibility\x18\x06\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\
|
||||
\x05width\x18\x07\x20\x01(\x05H\x05R\x05width\x12-\n\x0ctype_options\x18\
|
||||
\x08\x20\x01(\x0b2\x08.AnyDataH\x06R\x0btypeOptionsB\r\n\x0bone_of_nameB\
|
||||
\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_frozenB\
|
||||
\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x15\n\x13one_of_type\
|
||||
_options\"8\n\x07AnyData\x12\x17\n\x07type_id\x18\x01\x20\x01(\tR\x06typ\
|
||||
eId\x12\x14\n\x05value\x18\x02\x20\x01(\x0cR\x05value\"\xff\x01\n\x07Row\
|
||||
Meta\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12\x19\n\x08block_id\x18\
|
||||
\x02\x20\x01(\tR\x07blockId\x12D\n\x10cell_by_field_id\x18\x03\x20\x03(\
|
||||
\x0b2\x1b.RowMeta.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\
|
||||
\x18\x04\x20\x01(\x05R\x06height\x12\x1e\n\nvisibility\x18\x05\x20\x01(\
|
||||
\x08R\nvisibility\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\x03key\x18\x01\
|
||||
\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\x0b2\t.CellMetaR\
|
||||
\x05value:\x028\x01\"\xa7\x02\n\x10RowMetaChangeset\x12\x15\n\x06row_id\
|
||||
\x18\x01\x20\x01(\tR\x05rowId\x12\x18\n\x06height\x18\x02\x20\x01(\x05H\
|
||||
\0R\x06height\x12\x20\n\nvisibility\x18\x03\x20\x01(\x08H\x01R\nvisibili\
|
||||
ty\x12M\n\x10cell_by_field_id\x18\x04\x20\x03(\x0b2$.RowMetaChangeset.Ce\
|
||||
llByFieldIdEntryR\rcellByFieldId\x1aK\n\x12CellByFieldIdEntry\x12\x10\n\
|
||||
\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1f\n\x05value\x18\x02\x20\x01(\
|
||||
\x0b2\t.CellMetaR\x05value:\x028\x01B\x0f\n\rone_of_heightB\x13\n\x11one\
|
||||
_of_visibility\"\x82\x01\n\x08CellMeta\x12\x0e\n\x02id\x18\x01\x20\x01(\
|
||||
\tR\x02id\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\x08\
|
||||
field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x1c\n\x04data\x18\x04\x20\
|
||||
\x01(\x0b2\x08.AnyDataR\x04data\x12\x16\n\x06height\x18\x05\x20\x01(\x05\
|
||||
R\x06height*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\
|
||||
\x10\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\
|
||||
\x12\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06prot\
|
||||
o3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
@ -3,14 +3,14 @@ syntax = "proto3";
|
||||
message GridMeta {
|
||||
string grid_id = 1;
|
||||
repeated Field fields = 2;
|
||||
repeated Block blocks = 3;
|
||||
repeated GridBlock blocks = 3;
|
||||
}
|
||||
message Block {
|
||||
message GridBlock {
|
||||
string id = 1;
|
||||
int32 start_row_index = 2;
|
||||
int32 row_count = 3;
|
||||
}
|
||||
message BlockMeta {
|
||||
message GridBlockMeta {
|
||||
string block_id = 1;
|
||||
repeated RowMeta rows = 2;
|
||||
}
|
||||
@ -27,6 +27,16 @@ message Field {
|
||||
message RepeatedField {
|
||||
repeated Field items = 1;
|
||||
}
|
||||
message FieldChangeset {
|
||||
string field_id = 1;
|
||||
oneof one_of_name { string name = 2; };
|
||||
oneof one_of_desc { string desc = 3; };
|
||||
oneof one_of_field_type { FieldType field_type = 4; };
|
||||
oneof one_of_frozen { bool frozen = 5; };
|
||||
oneof one_of_visibility { bool visibility = 6; };
|
||||
oneof one_of_width { int32 width = 7; };
|
||||
oneof one_of_type_options { AnyData type_options = 8; };
|
||||
}
|
||||
message AnyData {
|
||||
string type_id = 1;
|
||||
bytes value = 2;
|
||||
|
Loading…
Reference in New Issue
Block a user