浏览代码

fix: #508 auto format number

appflowy 2 年之前
父节点
当前提交
84454469b4
共有 22 个文件被更改,包括 813 次插入682 次删除
  1. 9 10
      frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart
  2. 1 0
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart
  3. 1 1
      frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart
  4. 1 6
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/number_cell.dart
  5. 0 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart
  6. 1 1
      frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart
  7. 11 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pb.dart
  8. 94 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbenum.dart
  9. 55 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbjson.dart
  10. 9 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbserver.dart
  11. 5 7
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart
  12. 0 87
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart
  13. 0 45
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart
  14. 1 0
      frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart
  15. 207 0
      frontend/rust-lib/flowy-grid/src/protobuf/model/format.rs
  16. 3 0
      frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs
  17. 14 180
      frontend/rust-lib/flowy-grid/src/protobuf/model/number_type_option.rs
  18. 40 0
      frontend/rust-lib/flowy-grid/src/protobuf/proto/format.proto
  19. 1 38
      frontend/rust-lib/flowy-grid/src/protobuf/proto/number_type_option.proto
  20. 6 306
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/format.rs
  21. 6 0
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/mod.rs
  22. 348 0
      frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs

+ 9 - 10
frontend/app_flowy/lib/workspace/application/grid/cell/number_cell_bloc.dart

@@ -1,3 +1,4 @@
+import 'package:flowy_sdk/log.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';
@@ -14,25 +15,23 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
   }) : super(NumberCellState.initial(cellContext)) {
     on<NumberCellEvent>(
       (event, emit) async {
-        await event.map(
-          initial: (_Initial value) async {
+        await event.when(
+          initial: () async {
             _startListening();
           },
-          didReceiveCellUpdate: (_DidReceiveCellUpdate value) {
-            emit(state.copyWith(content: value.cellContent ?? ""));
+          didReceiveCellUpdate: (cellContent) {
+            emit(state.copyWith(content: cellContent ?? ""));
           },
-          updateCell: (_UpdateCell value) async {
-            await _updateCellValue(value, emit);
+          updateCell: (text) async {
+            cellContext.saveCellData(text, resultCallback: (result) {
+              result.fold(() => null, (err) => Log.error(err));
+            });
           },
         );
       },
     );
   }
 
-  Future<void> _updateCellValue(_UpdateCell value, Emitter<NumberCellState> emit) async {
-    cellContext.saveCellData(value.text);
-  }
-
   @override
   Future<void> close() async {
     if (_onCellChangedFn != null) {

+ 1 - 0
frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_bloc.dart

@@ -1,4 +1,5 @@
 import 'package:app_flowy/workspace/application/grid/field/type_option/type_option_service.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/application/grid/field/type_option/number_format_bloc.dart

@@ -1,4 +1,4 @@
-import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:freezed_annotation/freezed_annotation.dart';
 import 'dart:async';

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

@@ -87,12 +87,7 @@ class _NumberCellState extends State<NumberCell> {
       _delayOperation?.cancel();
       _delayOperation = Timer(const Duration(milliseconds: 300), () {
         if (_cellBloc.isClosed == false && _controller.text != _cellBloc.state.content) {
-          final number = num.tryParse(_controller.text);
-          if (number != null) {
-            _cellBloc.add(NumberCellEvent.updateCell(_controller.text));
-          } else {
-            _controller.text = "";
-          }
+          _cellBloc.add(NumberCellEvent.updateCell(_controller.text));
         }
       });
     }

+ 0 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/cell/select_option_cell/extension.dart

@@ -1,7 +1,6 @@
 import 'package:flowy_infra/theme.dart';
 import 'package:flowy_infra_ui/style_widget/hover.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
-import 'package:flowy_infra_ui/widget/spacing.dart';
 import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
 import 'package:flutter/material.dart';
 import 'package:easy_localization/easy_localization.dart';

+ 1 - 1
frontend/app_flowy/lib/workspace/presentation/plugins/grid/src/widgets/header/type_option/number.dart

@@ -9,7 +9,7 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
 import 'package:flowy_infra_ui/style_widget/button.dart';
 import 'package:flowy_infra_ui/style_widget/text.dart';
 import 'package:flowy_infra_ui/widget/spacing.dart';
-import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
+import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
 import 'package:flutter/material.dart';
 import 'package:flutter_bloc/flutter_bloc.dart';
 import 'package:easy_localization/easy_localization.dart' hide NumberFormat;

+ 11 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pb.dart

@@ -0,0 +1,11 @@
+///
+//  Generated code. Do not modify.
+//  source: format.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+import 'dart:core' as $core;
+
+export 'format.pbenum.dart';
+

+ 94 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbenum.dart

@@ -0,0 +1,94 @@
+///
+//  Generated code. Do not modify.
+//  source: format.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
+
+// ignore_for_file: UNDEFINED_SHOWN_NAME
+import 'dart:core' as $core;
+import 'package:protobuf/protobuf.dart' as $pb;
+
+class NumberFormat extends $pb.ProtobufEnum {
+  static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number');
+  static const NumberFormat USD = NumberFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD');
+  static const NumberFormat CanadianDollar = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CanadianDollar');
+  static const NumberFormat EUR = NumberFormat._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
+  static const NumberFormat Pound = NumberFormat._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Pound');
+  static const NumberFormat Yen = NumberFormat._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yen');
+  static const NumberFormat Ruble = NumberFormat._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ruble');
+  static const NumberFormat Rupee = NumberFormat._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupee');
+  static const NumberFormat Won = NumberFormat._(9, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Won');
+  static const NumberFormat Yuan = NumberFormat._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yuan');
+  static const NumberFormat Real = NumberFormat._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Real');
+  static const NumberFormat Lira = NumberFormat._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Lira');
+  static const NumberFormat Rupiah = NumberFormat._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupiah');
+  static const NumberFormat Franc = NumberFormat._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Franc');
+  static const NumberFormat HongKongDollar = NumberFormat._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'HongKongDollar');
+  static const NumberFormat NewZealandDollar = NumberFormat._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewZealandDollar');
+  static const NumberFormat Krona = NumberFormat._(17, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Krona');
+  static const NumberFormat NorwegianKrone = NumberFormat._(18, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NorwegianKrone');
+  static const NumberFormat MexicanPeso = NumberFormat._(19, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MexicanPeso');
+  static const NumberFormat Rand = NumberFormat._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rand');
+  static const NumberFormat NewTaiwanDollar = NumberFormat._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewTaiwanDollar');
+  static const NumberFormat DanishKrone = NumberFormat._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DanishKrone');
+  static const NumberFormat Baht = NumberFormat._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Baht');
+  static const NumberFormat Forint = NumberFormat._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Forint');
+  static const NumberFormat Koruna = NumberFormat._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Koruna');
+  static const NumberFormat Shekel = NumberFormat._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Shekel');
+  static const NumberFormat ChileanPeso = NumberFormat._(27, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ChileanPeso');
+  static const NumberFormat PhilippinePeso = NumberFormat._(28, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PhilippinePeso');
+  static const NumberFormat Dirham = NumberFormat._(29, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Dirham');
+  static const NumberFormat ColombianPeso = NumberFormat._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ColombianPeso');
+  static const NumberFormat Riyal = NumberFormat._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Riyal');
+  static const NumberFormat Ringgit = NumberFormat._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ringgit');
+  static const NumberFormat Leu = NumberFormat._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Leu');
+  static const NumberFormat ArgentinePeso = NumberFormat._(34, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ArgentinePeso');
+  static const NumberFormat UruguayanPeso = NumberFormat._(35, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UruguayanPeso');
+  static const NumberFormat Percent = NumberFormat._(36, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Percent');
+
+  static const $core.List<NumberFormat> values = <NumberFormat> [
+    Number,
+    USD,
+    CanadianDollar,
+    EUR,
+    Pound,
+    Yen,
+    Ruble,
+    Rupee,
+    Won,
+    Yuan,
+    Real,
+    Lira,
+    Rupiah,
+    Franc,
+    HongKongDollar,
+    NewZealandDollar,
+    Krona,
+    NorwegianKrone,
+    MexicanPeso,
+    Rand,
+    NewTaiwanDollar,
+    DanishKrone,
+    Baht,
+    Forint,
+    Koruna,
+    Shekel,
+    ChileanPeso,
+    PhilippinePeso,
+    Dirham,
+    ColombianPeso,
+    Riyal,
+    Ringgit,
+    Leu,
+    ArgentinePeso,
+    UruguayanPeso,
+    Percent,
+  ];
+
+  static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
+  static NumberFormat? valueOf($core.int value) => _byValue[value];
+
+  const NumberFormat._($core.int v, $core.String n) : super(v, n);
+}
+

+ 55 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbjson.dart

@@ -0,0 +1,55 @@
+///
+//  Generated code. Do not modify.
+//  source: format.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+import 'dart:core' as $core;
+import 'dart:convert' as $convert;
+import 'dart:typed_data' as $typed_data;
+@$core.Deprecated('Use numberFormatDescriptor instead')
+const NumberFormat$json = const {
+  '1': 'NumberFormat',
+  '2': const [
+    const {'1': 'Number', '2': 0},
+    const {'1': 'USD', '2': 1},
+    const {'1': 'CanadianDollar', '2': 2},
+    const {'1': 'EUR', '2': 4},
+    const {'1': 'Pound', '2': 5},
+    const {'1': 'Yen', '2': 6},
+    const {'1': 'Ruble', '2': 7},
+    const {'1': 'Rupee', '2': 8},
+    const {'1': 'Won', '2': 9},
+    const {'1': 'Yuan', '2': 10},
+    const {'1': 'Real', '2': 11},
+    const {'1': 'Lira', '2': 12},
+    const {'1': 'Rupiah', '2': 13},
+    const {'1': 'Franc', '2': 14},
+    const {'1': 'HongKongDollar', '2': 15},
+    const {'1': 'NewZealandDollar', '2': 16},
+    const {'1': 'Krona', '2': 17},
+    const {'1': 'NorwegianKrone', '2': 18},
+    const {'1': 'MexicanPeso', '2': 19},
+    const {'1': 'Rand', '2': 20},
+    const {'1': 'NewTaiwanDollar', '2': 21},
+    const {'1': 'DanishKrone', '2': 22},
+    const {'1': 'Baht', '2': 23},
+    const {'1': 'Forint', '2': 24},
+    const {'1': 'Koruna', '2': 25},
+    const {'1': 'Shekel', '2': 26},
+    const {'1': 'ChileanPeso', '2': 27},
+    const {'1': 'PhilippinePeso', '2': 28},
+    const {'1': 'Dirham', '2': 29},
+    const {'1': 'ColombianPeso', '2': 30},
+    const {'1': 'Riyal', '2': 31},
+    const {'1': 'Ringgit', '2': 32},
+    const {'1': 'Leu', '2': 33},
+    const {'1': 'ArgentinePeso', '2': 34},
+    const {'1': 'UruguayanPeso', '2': 35},
+    const {'1': 'Percent', '2': 36},
+  ],
+};
+
+/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
+final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESEgoOQ2FuYWRpYW5Eb2xsYXIQAhIHCgNFVVIQBBIJCgVQb3VuZBAFEgcKA1llbhAGEgkKBVJ1YmxlEAcSCQoFUnVwZWUQCBIHCgNXb24QCRIICgRZdWFuEAoSCAoEUmVhbBALEggKBExpcmEQDBIKCgZSdXBpYWgQDRIJCgVGcmFuYxAOEhIKDkhvbmdLb25nRG9sbGFyEA8SFAoQTmV3WmVhbGFuZERvbGxhchAQEgkKBUtyb25hEBESEgoOTm9yd2VnaWFuS3JvbmUQEhIPCgtNZXhpY2FuUGVzbxATEggKBFJhbmQQFBITCg9OZXdUYWl3YW5Eb2xsYXIQFRIPCgtEYW5pc2hLcm9uZRAWEggKBEJhaHQQFxIKCgZGb3JpbnQQGBIKCgZLb3J1bmEQGRIKCgZTaGVrZWwQGhIPCgtDaGlsZWFuUGVzbxAbEhIKDlBoaWxpcHBpbmVQZXNvEBwSCgoGRGlyaGFtEB0SEQoNQ29sb21iaWFuUGVzbxAeEgkKBVJpeWFsEB8SCwoHUmluZ2dpdBAgEgcKA0xldRAhEhEKDUFyZ2VudGluZVBlc28QIhIRCg1VcnVndWF5YW5QZXNvECMSCwoHUGVyY2VudBAk');

+ 9 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/format.pbserver.dart

@@ -0,0 +1,9 @@
+///
+//  Generated code. Do not modify.
+//  source: format.proto
+//
+// @dart = 2.12
+// ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields,deprecated_member_use_from_same_package
+
+export 'format.pb.dart';
+

+ 5 - 7
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pb.dart

@@ -9,13 +9,11 @@ import 'dart:core' as $core;
 
 import 'package:protobuf/protobuf.dart' as $pb;
 
-import 'number_type_option.pbenum.dart';
-
-export 'number_type_option.pbenum.dart';
+import 'format.pbenum.dart' as $0;
 
 class NumberTypeOption extends $pb.GeneratedMessage {
   static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'NumberTypeOption', createEmptyInstance: create)
-    ..e<NumberFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: NumberFormat.Number, valueOf: NumberFormat.valueOf, enumValues: NumberFormat.values)
+    ..e<$0.NumberFormat>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'format', $pb.PbFieldType.OE, defaultOrMaker: $0.NumberFormat.Number, valueOf: $0.NumberFormat.valueOf, enumValues: $0.NumberFormat.values)
     ..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'scale', $pb.PbFieldType.OU3)
     ..aOS(3, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'symbol')
     ..aOB(4, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'signPositive')
@@ -25,7 +23,7 @@ class NumberTypeOption extends $pb.GeneratedMessage {
 
   NumberTypeOption._() : super();
   factory NumberTypeOption({
-    NumberFormat? format,
+    $0.NumberFormat? format,
     $core.int? scale,
     $core.String? symbol,
     $core.bool? signPositive,
@@ -71,9 +69,9 @@ class NumberTypeOption extends $pb.GeneratedMessage {
   static NumberTypeOption? _defaultInstance;
 
   @$pb.TagNumber(1)
-  NumberFormat get format => $_getN(0);
+  $0.NumberFormat get format => $_getN(0);
   @$pb.TagNumber(1)
-  set format(NumberFormat v) { setField(1, v); }
+  set format($0.NumberFormat v) { setField(1, v); }
   @$pb.TagNumber(1)
   $core.bool hasFormat() => $_has(0);
   @$pb.TagNumber(1)

+ 0 - 87
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbenum.dart

@@ -5,90 +5,3 @@
 // @dart = 2.12
 // ignore_for_file: annotate_overrides,camel_case_types,unnecessary_const,non_constant_identifier_names,library_prefixes,unused_import,unused_shown_name,return_of_invalid_type,unnecessary_this,prefer_final_fields
 
-// ignore_for_file: UNDEFINED_SHOWN_NAME
-import 'dart:core' as $core;
-import 'package:protobuf/protobuf.dart' as $pb;
-
-class NumberFormat extends $pb.ProtobufEnum {
-  static const NumberFormat Number = NumberFormat._(0, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Number');
-  static const NumberFormat USD = NumberFormat._(1, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'USD');
-  static const NumberFormat CanadianDollar = NumberFormat._(2, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CanadianDollar');
-  static const NumberFormat EUR = NumberFormat._(4, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'EUR');
-  static const NumberFormat Pound = NumberFormat._(5, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Pound');
-  static const NumberFormat Yen = NumberFormat._(6, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yen');
-  static const NumberFormat Ruble = NumberFormat._(7, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ruble');
-  static const NumberFormat Rupee = NumberFormat._(8, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupee');
-  static const NumberFormat Won = NumberFormat._(9, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Won');
-  static const NumberFormat Yuan = NumberFormat._(10, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Yuan');
-  static const NumberFormat Real = NumberFormat._(11, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Real');
-  static const NumberFormat Lira = NumberFormat._(12, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Lira');
-  static const NumberFormat Rupiah = NumberFormat._(13, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rupiah');
-  static const NumberFormat Franc = NumberFormat._(14, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Franc');
-  static const NumberFormat HongKongDollar = NumberFormat._(15, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'HongKongDollar');
-  static const NumberFormat NewZealandDollar = NumberFormat._(16, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewZealandDollar');
-  static const NumberFormat Krona = NumberFormat._(17, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Krona');
-  static const NumberFormat NorwegianKrone = NumberFormat._(18, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NorwegianKrone');
-  static const NumberFormat MexicanPeso = NumberFormat._(19, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'MexicanPeso');
-  static const NumberFormat Rand = NumberFormat._(20, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Rand');
-  static const NumberFormat NewTaiwanDollar = NumberFormat._(21, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'NewTaiwanDollar');
-  static const NumberFormat DanishKrone = NumberFormat._(22, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DanishKrone');
-  static const NumberFormat Baht = NumberFormat._(23, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Baht');
-  static const NumberFormat Forint = NumberFormat._(24, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Forint');
-  static const NumberFormat Koruna = NumberFormat._(25, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Koruna');
-  static const NumberFormat Shekel = NumberFormat._(26, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Shekel');
-  static const NumberFormat ChileanPeso = NumberFormat._(27, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ChileanPeso');
-  static const NumberFormat PhilippinePeso = NumberFormat._(28, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'PhilippinePeso');
-  static const NumberFormat Dirham = NumberFormat._(29, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Dirham');
-  static const NumberFormat ColombianPeso = NumberFormat._(30, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ColombianPeso');
-  static const NumberFormat Riyal = NumberFormat._(31, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Riyal');
-  static const NumberFormat Ringgit = NumberFormat._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Ringgit');
-  static const NumberFormat Leu = NumberFormat._(33, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Leu');
-  static const NumberFormat ArgentinePeso = NumberFormat._(34, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ArgentinePeso');
-  static const NumberFormat UruguayanPeso = NumberFormat._(35, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UruguayanPeso');
-  static const NumberFormat Percent = NumberFormat._(36, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'Percent');
-
-  static const $core.List<NumberFormat> values = <NumberFormat> [
-    Number,
-    USD,
-    CanadianDollar,
-    EUR,
-    Pound,
-    Yen,
-    Ruble,
-    Rupee,
-    Won,
-    Yuan,
-    Real,
-    Lira,
-    Rupiah,
-    Franc,
-    HongKongDollar,
-    NewZealandDollar,
-    Krona,
-    NorwegianKrone,
-    MexicanPeso,
-    Rand,
-    NewTaiwanDollar,
-    DanishKrone,
-    Baht,
-    Forint,
-    Koruna,
-    Shekel,
-    ChileanPeso,
-    PhilippinePeso,
-    Dirham,
-    ColombianPeso,
-    Riyal,
-    Ringgit,
-    Leu,
-    ArgentinePeso,
-    UruguayanPeso,
-    Percent,
-  ];
-
-  static final $core.Map<$core.int, NumberFormat> _byValue = $pb.ProtobufEnum.initByValue(values);
-  static NumberFormat? valueOf($core.int value) => _byValue[value];
-
-  const NumberFormat._($core.int v, $core.String n) : super(v, n);
-}
-

+ 0 - 45
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/number_type_option.pbjson.dart

@@ -8,51 +8,6 @@
 import 'dart:core' as $core;
 import 'dart:convert' as $convert;
 import 'dart:typed_data' as $typed_data;
-@$core.Deprecated('Use numberFormatDescriptor instead')
-const NumberFormat$json = const {
-  '1': 'NumberFormat',
-  '2': const [
-    const {'1': 'Number', '2': 0},
-    const {'1': 'USD', '2': 1},
-    const {'1': 'CanadianDollar', '2': 2},
-    const {'1': 'EUR', '2': 4},
-    const {'1': 'Pound', '2': 5},
-    const {'1': 'Yen', '2': 6},
-    const {'1': 'Ruble', '2': 7},
-    const {'1': 'Rupee', '2': 8},
-    const {'1': 'Won', '2': 9},
-    const {'1': 'Yuan', '2': 10},
-    const {'1': 'Real', '2': 11},
-    const {'1': 'Lira', '2': 12},
-    const {'1': 'Rupiah', '2': 13},
-    const {'1': 'Franc', '2': 14},
-    const {'1': 'HongKongDollar', '2': 15},
-    const {'1': 'NewZealandDollar', '2': 16},
-    const {'1': 'Krona', '2': 17},
-    const {'1': 'NorwegianKrone', '2': 18},
-    const {'1': 'MexicanPeso', '2': 19},
-    const {'1': 'Rand', '2': 20},
-    const {'1': 'NewTaiwanDollar', '2': 21},
-    const {'1': 'DanishKrone', '2': 22},
-    const {'1': 'Baht', '2': 23},
-    const {'1': 'Forint', '2': 24},
-    const {'1': 'Koruna', '2': 25},
-    const {'1': 'Shekel', '2': 26},
-    const {'1': 'ChileanPeso', '2': 27},
-    const {'1': 'PhilippinePeso', '2': 28},
-    const {'1': 'Dirham', '2': 29},
-    const {'1': 'ColombianPeso', '2': 30},
-    const {'1': 'Riyal', '2': 31},
-    const {'1': 'Ringgit', '2': 32},
-    const {'1': 'Leu', '2': 33},
-    const {'1': 'ArgentinePeso', '2': 34},
-    const {'1': 'UruguayanPeso', '2': 35},
-    const {'1': 'Percent', '2': 36},
-  ],
-};
-
-/// Descriptor for `NumberFormat`. Decode as a `google.protobuf.EnumDescriptorProto`.
-final $typed_data.Uint8List numberFormatDescriptor = $convert.base64Decode('CgxOdW1iZXJGb3JtYXQSCgoGTnVtYmVyEAASBwoDVVNEEAESEgoOQ2FuYWRpYW5Eb2xsYXIQAhIHCgNFVVIQBBIJCgVQb3VuZBAFEgcKA1llbhAGEgkKBVJ1YmxlEAcSCQoFUnVwZWUQCBIHCgNXb24QCRIICgRZdWFuEAoSCAoEUmVhbBALEggKBExpcmEQDBIKCgZSdXBpYWgQDRIJCgVGcmFuYxAOEhIKDkhvbmdLb25nRG9sbGFyEA8SFAoQTmV3WmVhbGFuZERvbGxhchAQEgkKBUtyb25hEBESEgoOTm9yd2VnaWFuS3JvbmUQEhIPCgtNZXhpY2FuUGVzbxATEggKBFJhbmQQFBITCg9OZXdUYWl3YW5Eb2xsYXIQFRIPCgtEYW5pc2hLcm9uZRAWEggKBEJhaHQQFxIKCgZGb3JpbnQQGBIKCgZLb3J1bmEQGRIKCgZTaGVrZWwQGhIPCgtDaGlsZWFuUGVzbxAbEhIKDlBoaWxpcHBpbmVQZXNvEBwSCgoGRGlyaGFtEB0SEQoNQ29sb21iaWFuUGVzbxAeEgkKBVJpeWFsEB8SCwoHUmluZ2dpdBAgEgcKA0xldRAhEhEKDUFyZ2VudGluZVBlc28QIhIRCg1VcnVndWF5YW5QZXNvECMSCwoHUGVyY2VudBAk');
 @$core.Deprecated('Use numberTypeOptionDescriptor instead')
 const NumberTypeOption$json = const {
   '1': 'NumberTypeOption',

+ 1 - 0
frontend/app_flowy/packages/flowy_sdk/lib/protobuf/flowy-grid/protobuf.dart

@@ -7,6 +7,7 @@ export './row_entities.pb.dart';
 export './cell_entities.pb.dart';
 export './url_type_option.pb.dart';
 export './checkbox_type_option.pb.dart';
+export './format.pb.dart';
 export './event_map.pb.dart';
 export './text_type_option.pb.dart';
 export './date_type_option.pb.dart';

+ 207 - 0
frontend/rust-lib/flowy-grid/src/protobuf/model/format.rs

@@ -0,0 +1,207 @@
+// This file is generated by rust-protobuf 2.25.2. Do not edit
+// @generated
+
+// https://github.com/rust-lang/rust-clippy/issues/702
+#![allow(unknown_lints)]
+#![allow(clippy::all)]
+
+#![allow(unused_attributes)]
+#![cfg_attr(rustfmt, rustfmt::skip)]
+
+#![allow(box_pointers)]
+#![allow(dead_code)]
+#![allow(missing_docs)]
+#![allow(non_camel_case_types)]
+#![allow(non_snake_case)]
+#![allow(non_upper_case_globals)]
+#![allow(trivial_casts)]
+#![allow(unused_imports)]
+#![allow(unused_results)]
+//! Generated file from `format.proto`
+
+/// Generated files are compatible only with the same version
+/// of protobuf runtime.
+// const _PROTOBUF_VERSION_CHECK: () = ::protobuf::VERSION_2_25_2;
+
+#[derive(Clone,PartialEq,Eq,Debug,Hash)]
+pub enum NumberFormat {
+    Number = 0,
+    USD = 1,
+    CanadianDollar = 2,
+    EUR = 4,
+    Pound = 5,
+    Yen = 6,
+    Ruble = 7,
+    Rupee = 8,
+    Won = 9,
+    Yuan = 10,
+    Real = 11,
+    Lira = 12,
+    Rupiah = 13,
+    Franc = 14,
+    HongKongDollar = 15,
+    NewZealandDollar = 16,
+    Krona = 17,
+    NorwegianKrone = 18,
+    MexicanPeso = 19,
+    Rand = 20,
+    NewTaiwanDollar = 21,
+    DanishKrone = 22,
+    Baht = 23,
+    Forint = 24,
+    Koruna = 25,
+    Shekel = 26,
+    ChileanPeso = 27,
+    PhilippinePeso = 28,
+    Dirham = 29,
+    ColombianPeso = 30,
+    Riyal = 31,
+    Ringgit = 32,
+    Leu = 33,
+    ArgentinePeso = 34,
+    UruguayanPeso = 35,
+    Percent = 36,
+}
+
+impl ::protobuf::ProtobufEnum for NumberFormat {
+    fn value(&self) -> i32 {
+        *self as i32
+    }
+
+    fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
+        match value {
+            0 => ::std::option::Option::Some(NumberFormat::Number),
+            1 => ::std::option::Option::Some(NumberFormat::USD),
+            2 => ::std::option::Option::Some(NumberFormat::CanadianDollar),
+            4 => ::std::option::Option::Some(NumberFormat::EUR),
+            5 => ::std::option::Option::Some(NumberFormat::Pound),
+            6 => ::std::option::Option::Some(NumberFormat::Yen),
+            7 => ::std::option::Option::Some(NumberFormat::Ruble),
+            8 => ::std::option::Option::Some(NumberFormat::Rupee),
+            9 => ::std::option::Option::Some(NumberFormat::Won),
+            10 => ::std::option::Option::Some(NumberFormat::Yuan),
+            11 => ::std::option::Option::Some(NumberFormat::Real),
+            12 => ::std::option::Option::Some(NumberFormat::Lira),
+            13 => ::std::option::Option::Some(NumberFormat::Rupiah),
+            14 => ::std::option::Option::Some(NumberFormat::Franc),
+            15 => ::std::option::Option::Some(NumberFormat::HongKongDollar),
+            16 => ::std::option::Option::Some(NumberFormat::NewZealandDollar),
+            17 => ::std::option::Option::Some(NumberFormat::Krona),
+            18 => ::std::option::Option::Some(NumberFormat::NorwegianKrone),
+            19 => ::std::option::Option::Some(NumberFormat::MexicanPeso),
+            20 => ::std::option::Option::Some(NumberFormat::Rand),
+            21 => ::std::option::Option::Some(NumberFormat::NewTaiwanDollar),
+            22 => ::std::option::Option::Some(NumberFormat::DanishKrone),
+            23 => ::std::option::Option::Some(NumberFormat::Baht),
+            24 => ::std::option::Option::Some(NumberFormat::Forint),
+            25 => ::std::option::Option::Some(NumberFormat::Koruna),
+            26 => ::std::option::Option::Some(NumberFormat::Shekel),
+            27 => ::std::option::Option::Some(NumberFormat::ChileanPeso),
+            28 => ::std::option::Option::Some(NumberFormat::PhilippinePeso),
+            29 => ::std::option::Option::Some(NumberFormat::Dirham),
+            30 => ::std::option::Option::Some(NumberFormat::ColombianPeso),
+            31 => ::std::option::Option::Some(NumberFormat::Riyal),
+            32 => ::std::option::Option::Some(NumberFormat::Ringgit),
+            33 => ::std::option::Option::Some(NumberFormat::Leu),
+            34 => ::std::option::Option::Some(NumberFormat::ArgentinePeso),
+            35 => ::std::option::Option::Some(NumberFormat::UruguayanPeso),
+            36 => ::std::option::Option::Some(NumberFormat::Percent),
+            _ => ::std::option::Option::None
+        }
+    }
+
+    fn values() -> &'static [Self] {
+        static values: &'static [NumberFormat] = &[
+            NumberFormat::Number,
+            NumberFormat::USD,
+            NumberFormat::CanadianDollar,
+            NumberFormat::EUR,
+            NumberFormat::Pound,
+            NumberFormat::Yen,
+            NumberFormat::Ruble,
+            NumberFormat::Rupee,
+            NumberFormat::Won,
+            NumberFormat::Yuan,
+            NumberFormat::Real,
+            NumberFormat::Lira,
+            NumberFormat::Rupiah,
+            NumberFormat::Franc,
+            NumberFormat::HongKongDollar,
+            NumberFormat::NewZealandDollar,
+            NumberFormat::Krona,
+            NumberFormat::NorwegianKrone,
+            NumberFormat::MexicanPeso,
+            NumberFormat::Rand,
+            NumberFormat::NewTaiwanDollar,
+            NumberFormat::DanishKrone,
+            NumberFormat::Baht,
+            NumberFormat::Forint,
+            NumberFormat::Koruna,
+            NumberFormat::Shekel,
+            NumberFormat::ChileanPeso,
+            NumberFormat::PhilippinePeso,
+            NumberFormat::Dirham,
+            NumberFormat::ColombianPeso,
+            NumberFormat::Riyal,
+            NumberFormat::Ringgit,
+            NumberFormat::Leu,
+            NumberFormat::ArgentinePeso,
+            NumberFormat::UruguayanPeso,
+            NumberFormat::Percent,
+        ];
+        values
+    }
+
+    fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
+        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
+        descriptor.get(|| {
+            ::protobuf::reflect::EnumDescriptor::new_pb_name::<NumberFormat>("NumberFormat", file_descriptor_proto())
+        })
+    }
+}
+
+impl ::std::marker::Copy for NumberFormat {
+}
+
+impl ::std::default::Default for NumberFormat {
+    fn default() -> Self {
+        NumberFormat::Number
+    }
+}
+
+impl ::protobuf::reflect::ProtobufValue for NumberFormat {
+    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
+        ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
+    }
+}
+
+static file_descriptor_proto_data: &'static [u8] = b"\
+    \n\x0cformat.proto*\xf8\x03\n\x0cNumberFormat\x12\n\n\x06Number\x10\0\
+    \x12\x07\n\x03USD\x10\x01\x12\x12\n\x0eCanadianDollar\x10\x02\x12\x07\n\
+    \x03EUR\x10\x04\x12\t\n\x05Pound\x10\x05\x12\x07\n\x03Yen\x10\x06\x12\t\
+    \n\x05Ruble\x10\x07\x12\t\n\x05Rupee\x10\x08\x12\x07\n\x03Won\x10\t\x12\
+    \x08\n\x04Yuan\x10\n\x12\x08\n\x04Real\x10\x0b\x12\x08\n\x04Lira\x10\x0c\
+    \x12\n\n\x06Rupiah\x10\r\x12\t\n\x05Franc\x10\x0e\x12\x12\n\x0eHongKongD\
+    ollar\x10\x0f\x12\x14\n\x10NewZealandDollar\x10\x10\x12\t\n\x05Krona\x10\
+    \x11\x12\x12\n\x0eNorwegianKrone\x10\x12\x12\x0f\n\x0bMexicanPeso\x10\
+    \x13\x12\x08\n\x04Rand\x10\x14\x12\x13\n\x0fNewTaiwanDollar\x10\x15\x12\
+    \x0f\n\x0bDanishKrone\x10\x16\x12\x08\n\x04Baht\x10\x17\x12\n\n\x06Forin\
+    t\x10\x18\x12\n\n\x06Koruna\x10\x19\x12\n\n\x06Shekel\x10\x1a\x12\x0f\n\
+    \x0bChileanPeso\x10\x1b\x12\x12\n\x0ePhilippinePeso\x10\x1c\x12\n\n\x06D\
+    irham\x10\x1d\x12\x11\n\rColombianPeso\x10\x1e\x12\t\n\x05Riyal\x10\x1f\
+    \x12\x0b\n\x07Ringgit\x10\x20\x12\x07\n\x03Leu\x10!\x12\x11\n\rArgentine\
+    Peso\x10\"\x12\x11\n\rUruguayanPeso\x10#\x12\x0b\n\x07Percent\x10$b\x06p\
+    roto3\
+";
+
+static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
+
+fn parse_descriptor_proto() -> ::protobuf::descriptor::FileDescriptorProto {
+    ::protobuf::Message::parse_from_bytes(file_descriptor_proto_data).unwrap()
+}
+
+pub fn file_descriptor_proto() -> &'static ::protobuf::descriptor::FileDescriptorProto {
+    file_descriptor_proto_lazy.get(|| {
+        parse_descriptor_proto()
+    })
+}

+ 3 - 0
frontend/rust-lib/flowy-grid/src/protobuf/model/mod.rs

@@ -25,6 +25,9 @@ pub use url_type_option::*;
 mod checkbox_type_option;
 pub use checkbox_type_option::*;
 
+mod format;
+pub use format::*;
+
 mod event_map;
 pub use event_map::*;
 

+ 14 - 180
frontend/rust-lib/flowy-grid/src/protobuf/model/number_type_option.rs

@@ -26,7 +26,7 @@
 #[derive(PartialEq,Clone,Default)]
 pub struct NumberTypeOption {
     // message fields
-    pub format: NumberFormat,
+    pub format: super::format::NumberFormat,
     pub scale: u32,
     pub symbol: ::std::string::String,
     pub sign_positive: bool,
@@ -50,15 +50,15 @@ impl NumberTypeOption {
     // .NumberFormat format = 1;
 
 
-    pub fn get_format(&self) -> NumberFormat {
+    pub fn get_format(&self) -> super::format::NumberFormat {
         self.format
     }
     pub fn clear_format(&mut self) {
-        self.format = NumberFormat::Number;
+        self.format = super::format::NumberFormat::Number;
     }
 
     // Param is passed by value, moved
-    pub fn set_format(&mut self, v: NumberFormat) {
+    pub fn set_format(&mut self, v: super::format::NumberFormat) {
         self.format = v;
     }
 
@@ -189,7 +189,7 @@ impl ::protobuf::Message for NumberTypeOption {
     #[allow(unused_variables)]
     fn compute_size(&self) -> u32 {
         let mut my_size = 0;
-        if self.format != NumberFormat::Number {
+        if self.format != super::format::NumberFormat::Number {
             my_size += ::protobuf::rt::enum_size(1, self.format);
         }
         if self.scale != 0 {
@@ -210,7 +210,7 @@ impl ::protobuf::Message for NumberTypeOption {
     }
 
     fn write_to_with_cached_sizes(&self, os: &mut ::protobuf::CodedOutputStream<'_>) -> ::protobuf::ProtobufResult<()> {
-        if self.format != NumberFormat::Number {
+        if self.format != super::format::NumberFormat::Number {
             os.write_enum(1, ::protobuf::ProtobufEnum::value(&self.format))?;
         }
         if self.scale != 0 {
@@ -263,7 +263,7 @@ impl ::protobuf::Message for NumberTypeOption {
         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::ProtobufTypeEnum<NumberFormat>>(
+            fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeEnum<super::format::NumberFormat>>(
                 "format",
                 |m: &NumberTypeOption| { &m.format },
                 |m: &mut NumberTypeOption| { &mut m.format },
@@ -304,7 +304,7 @@ impl ::protobuf::Message for NumberTypeOption {
 
 impl ::protobuf::Clear for NumberTypeOption {
     fn clear(&mut self) {
-        self.format = NumberFormat::Number;
+        self.format = super::format::NumberFormat::Number;
         self.scale = 0;
         self.symbol.clear();
         self.sign_positive = false;
@@ -325,179 +325,13 @@ impl ::protobuf::reflect::ProtobufValue for NumberTypeOption {
     }
 }
 
-#[derive(Clone,PartialEq,Eq,Debug,Hash)]
-pub enum NumberFormat {
-    Number = 0,
-    USD = 1,
-    CanadianDollar = 2,
-    EUR = 4,
-    Pound = 5,
-    Yen = 6,
-    Ruble = 7,
-    Rupee = 8,
-    Won = 9,
-    Yuan = 10,
-    Real = 11,
-    Lira = 12,
-    Rupiah = 13,
-    Franc = 14,
-    HongKongDollar = 15,
-    NewZealandDollar = 16,
-    Krona = 17,
-    NorwegianKrone = 18,
-    MexicanPeso = 19,
-    Rand = 20,
-    NewTaiwanDollar = 21,
-    DanishKrone = 22,
-    Baht = 23,
-    Forint = 24,
-    Koruna = 25,
-    Shekel = 26,
-    ChileanPeso = 27,
-    PhilippinePeso = 28,
-    Dirham = 29,
-    ColombianPeso = 30,
-    Riyal = 31,
-    Ringgit = 32,
-    Leu = 33,
-    ArgentinePeso = 34,
-    UruguayanPeso = 35,
-    Percent = 36,
-}
-
-impl ::protobuf::ProtobufEnum for NumberFormat {
-    fn value(&self) -> i32 {
-        *self as i32
-    }
-
-    fn from_i32(value: i32) -> ::std::option::Option<NumberFormat> {
-        match value {
-            0 => ::std::option::Option::Some(NumberFormat::Number),
-            1 => ::std::option::Option::Some(NumberFormat::USD),
-            2 => ::std::option::Option::Some(NumberFormat::CanadianDollar),
-            4 => ::std::option::Option::Some(NumberFormat::EUR),
-            5 => ::std::option::Option::Some(NumberFormat::Pound),
-            6 => ::std::option::Option::Some(NumberFormat::Yen),
-            7 => ::std::option::Option::Some(NumberFormat::Ruble),
-            8 => ::std::option::Option::Some(NumberFormat::Rupee),
-            9 => ::std::option::Option::Some(NumberFormat::Won),
-            10 => ::std::option::Option::Some(NumberFormat::Yuan),
-            11 => ::std::option::Option::Some(NumberFormat::Real),
-            12 => ::std::option::Option::Some(NumberFormat::Lira),
-            13 => ::std::option::Option::Some(NumberFormat::Rupiah),
-            14 => ::std::option::Option::Some(NumberFormat::Franc),
-            15 => ::std::option::Option::Some(NumberFormat::HongKongDollar),
-            16 => ::std::option::Option::Some(NumberFormat::NewZealandDollar),
-            17 => ::std::option::Option::Some(NumberFormat::Krona),
-            18 => ::std::option::Option::Some(NumberFormat::NorwegianKrone),
-            19 => ::std::option::Option::Some(NumberFormat::MexicanPeso),
-            20 => ::std::option::Option::Some(NumberFormat::Rand),
-            21 => ::std::option::Option::Some(NumberFormat::NewTaiwanDollar),
-            22 => ::std::option::Option::Some(NumberFormat::DanishKrone),
-            23 => ::std::option::Option::Some(NumberFormat::Baht),
-            24 => ::std::option::Option::Some(NumberFormat::Forint),
-            25 => ::std::option::Option::Some(NumberFormat::Koruna),
-            26 => ::std::option::Option::Some(NumberFormat::Shekel),
-            27 => ::std::option::Option::Some(NumberFormat::ChileanPeso),
-            28 => ::std::option::Option::Some(NumberFormat::PhilippinePeso),
-            29 => ::std::option::Option::Some(NumberFormat::Dirham),
-            30 => ::std::option::Option::Some(NumberFormat::ColombianPeso),
-            31 => ::std::option::Option::Some(NumberFormat::Riyal),
-            32 => ::std::option::Option::Some(NumberFormat::Ringgit),
-            33 => ::std::option::Option::Some(NumberFormat::Leu),
-            34 => ::std::option::Option::Some(NumberFormat::ArgentinePeso),
-            35 => ::std::option::Option::Some(NumberFormat::UruguayanPeso),
-            36 => ::std::option::Option::Some(NumberFormat::Percent),
-            _ => ::std::option::Option::None
-        }
-    }
-
-    fn values() -> &'static [Self] {
-        static values: &'static [NumberFormat] = &[
-            NumberFormat::Number,
-            NumberFormat::USD,
-            NumberFormat::CanadianDollar,
-            NumberFormat::EUR,
-            NumberFormat::Pound,
-            NumberFormat::Yen,
-            NumberFormat::Ruble,
-            NumberFormat::Rupee,
-            NumberFormat::Won,
-            NumberFormat::Yuan,
-            NumberFormat::Real,
-            NumberFormat::Lira,
-            NumberFormat::Rupiah,
-            NumberFormat::Franc,
-            NumberFormat::HongKongDollar,
-            NumberFormat::NewZealandDollar,
-            NumberFormat::Krona,
-            NumberFormat::NorwegianKrone,
-            NumberFormat::MexicanPeso,
-            NumberFormat::Rand,
-            NumberFormat::NewTaiwanDollar,
-            NumberFormat::DanishKrone,
-            NumberFormat::Baht,
-            NumberFormat::Forint,
-            NumberFormat::Koruna,
-            NumberFormat::Shekel,
-            NumberFormat::ChileanPeso,
-            NumberFormat::PhilippinePeso,
-            NumberFormat::Dirham,
-            NumberFormat::ColombianPeso,
-            NumberFormat::Riyal,
-            NumberFormat::Ringgit,
-            NumberFormat::Leu,
-            NumberFormat::ArgentinePeso,
-            NumberFormat::UruguayanPeso,
-            NumberFormat::Percent,
-        ];
-        values
-    }
-
-    fn enum_descriptor_static() -> &'static ::protobuf::reflect::EnumDescriptor {
-        static descriptor: ::protobuf::rt::LazyV2<::protobuf::reflect::EnumDescriptor> = ::protobuf::rt::LazyV2::INIT;
-        descriptor.get(|| {
-            ::protobuf::reflect::EnumDescriptor::new_pb_name::<NumberFormat>("NumberFormat", file_descriptor_proto())
-        })
-    }
-}
-
-impl ::std::marker::Copy for NumberFormat {
-}
-
-impl ::std::default::Default for NumberFormat {
-    fn default() -> Self {
-        NumberFormat::Number
-    }
-}
-
-impl ::protobuf::reflect::ProtobufValue for NumberFormat {
-    fn as_ref(&self) -> ::protobuf::reflect::ReflectValueRef {
-        ::protobuf::reflect::ReflectValueRef::Enum(::protobuf::ProtobufEnum::descriptor(self))
-    }
-}
-
 static file_descriptor_proto_data: &'static [u8] = b"\
-    \n\x18number_type_option.proto\"\xa0\x01\n\x10NumberTypeOption\x12%\n\
-    \x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06format\x12\x14\n\x05\
-    scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\x18\x03\x20\x01(\
-    \tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\x08R\x0csignPositiv\
-    e\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04name*\xf8\x03\n\x0cNumberForm\
-    at\x12\n\n\x06Number\x10\0\x12\x07\n\x03USD\x10\x01\x12\x12\n\x0eCanadia\
-    nDollar\x10\x02\x12\x07\n\x03EUR\x10\x04\x12\t\n\x05Pound\x10\x05\x12\
-    \x07\n\x03Yen\x10\x06\x12\t\n\x05Ruble\x10\x07\x12\t\n\x05Rupee\x10\x08\
-    \x12\x07\n\x03Won\x10\t\x12\x08\n\x04Yuan\x10\n\x12\x08\n\x04Real\x10\
-    \x0b\x12\x08\n\x04Lira\x10\x0c\x12\n\n\x06Rupiah\x10\r\x12\t\n\x05Franc\
-    \x10\x0e\x12\x12\n\x0eHongKongDollar\x10\x0f\x12\x14\n\x10NewZealandDoll\
-    ar\x10\x10\x12\t\n\x05Krona\x10\x11\x12\x12\n\x0eNorwegianKrone\x10\x12\
-    \x12\x0f\n\x0bMexicanPeso\x10\x13\x12\x08\n\x04Rand\x10\x14\x12\x13\n\
-    \x0fNewTaiwanDollar\x10\x15\x12\x0f\n\x0bDanishKrone\x10\x16\x12\x08\n\
-    \x04Baht\x10\x17\x12\n\n\x06Forint\x10\x18\x12\n\n\x06Koruna\x10\x19\x12\
-    \n\n\x06Shekel\x10\x1a\x12\x0f\n\x0bChileanPeso\x10\x1b\x12\x12\n\x0ePhi\
-    lippinePeso\x10\x1c\x12\n\n\x06Dirham\x10\x1d\x12\x11\n\rColombianPeso\
-    \x10\x1e\x12\t\n\x05Riyal\x10\x1f\x12\x0b\n\x07Ringgit\x10\x20\x12\x07\n\
-    \x03Leu\x10!\x12\x11\n\rArgentinePeso\x10\"\x12\x11\n\rUruguayanPeso\x10\
-    #\x12\x0b\n\x07Percent\x10$b\x06proto3\
+    \n\x18number_type_option.proto\x1a\x0cformat.proto\"\xa0\x01\n\x10Number\
+    TypeOption\x12%\n\x06format\x18\x01\x20\x01(\x0e2\r.NumberFormatR\x06for\
+    mat\x12\x14\n\x05scale\x18\x02\x20\x01(\rR\x05scale\x12\x16\n\x06symbol\
+    \x18\x03\x20\x01(\tR\x06symbol\x12#\n\rsign_positive\x18\x04\x20\x01(\
+    \x08R\x0csignPositive\x12\x12\n\x04name\x18\x05\x20\x01(\tR\x04nameb\x06\
+    proto3\
 ";
 
 static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;

+ 40 - 0
frontend/rust-lib/flowy-grid/src/protobuf/proto/format.proto

@@ -0,0 +1,40 @@
+syntax = "proto3";
+
+enum NumberFormat {
+    Number = 0;
+    USD = 1;
+    CanadianDollar = 2;
+    EUR = 4;
+    Pound = 5;
+    Yen = 6;
+    Ruble = 7;
+    Rupee = 8;
+    Won = 9;
+    Yuan = 10;
+    Real = 11;
+    Lira = 12;
+    Rupiah = 13;
+    Franc = 14;
+    HongKongDollar = 15;
+    NewZealandDollar = 16;
+    Krona = 17;
+    NorwegianKrone = 18;
+    MexicanPeso = 19;
+    Rand = 20;
+    NewTaiwanDollar = 21;
+    DanishKrone = 22;
+    Baht = 23;
+    Forint = 24;
+    Koruna = 25;
+    Shekel = 26;
+    ChileanPeso = 27;
+    PhilippinePeso = 28;
+    Dirham = 29;
+    ColombianPeso = 30;
+    Riyal = 31;
+    Ringgit = 32;
+    Leu = 33;
+    ArgentinePeso = 34;
+    UruguayanPeso = 35;
+    Percent = 36;
+}

+ 1 - 38
frontend/rust-lib/flowy-grid/src/protobuf/proto/number_type_option.proto

@@ -1,4 +1,5 @@
 syntax = "proto3";
+import "format.proto";
 
 message NumberTypeOption {
     NumberFormat format = 1;
@@ -7,41 +8,3 @@ message NumberTypeOption {
     bool sign_positive = 4;
     string name = 5;
 }
-enum NumberFormat {
-    Number = 0;
-    USD = 1;
-    CanadianDollar = 2;
-    EUR = 4;
-    Pound = 5;
-    Yen = 6;
-    Ruble = 7;
-    Rupee = 8;
-    Won = 9;
-    Yuan = 10;
-    Real = 11;
-    Lira = 12;
-    Rupiah = 13;
-    Franc = 14;
-    HongKongDollar = 15;
-    NewZealandDollar = 16;
-    Krona = 17;
-    NorwegianKrone = 18;
-    MexicanPeso = 19;
-    Rand = 20;
-    NewTaiwanDollar = 21;
-    DanishKrone = 22;
-    Baht = 23;
-    Forint = 24;
-    Koruna = 25;
-    Shekel = 26;
-    ChileanPeso = 27;
-    PhilippinePeso = 28;
-    Dirham = 29;
-    ColombianPeso = 30;
-    Riyal = 31;
-    Ringgit = 32;
-    Leu = 33;
-    ArgentinePeso = 34;
-    UruguayanPeso = 35;
-    Percent = 36;
-}

+ 6 - 306
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option.rs → frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/format.rs

@@ -1,182 +1,16 @@
-use crate::impl_type_option;
-use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
-use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
-use bytes::Bytes;
-use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
-use flowy_error::{FlowyError, FlowyResult};
-use flowy_grid_data_model::entities::{
-    CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
-};
+use flowy_derive::ProtoBuf_Enum;
 use lazy_static::lazy_static;
-use rust_decimal::Decimal;
+
 use rusty_money::define_currency_set;
 use serde::{Deserialize, Serialize};
-use std::str::FromStr;
 use strum::IntoEnumIterator;
 use strum_macros::EnumIter;
 
 lazy_static! {
-    static ref STRIP_SYMBOL: Vec<String> = make_strip_symbol();
-}
-
-#[derive(Default)]
-pub struct NumberTypeOptionBuilder(NumberTypeOption);
-impl_into_box_type_option_builder!(NumberTypeOptionBuilder);
-impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption);
-
-impl NumberTypeOptionBuilder {
-    pub fn name(mut self, name: &str) -> Self {
-        self.0.name = name.to_string();
-        self
-    }
-
-    pub fn set_format(mut self, format: NumberFormat) -> Self {
-        self.0.set_format(format);
-        self
-    }
-
-    pub fn scale(mut self, scale: u32) -> Self {
-        self.0.scale = scale;
-        self
-    }
-
-    pub fn positive(mut self, positive: bool) -> Self {
-        self.0.sign_positive = positive;
-        self
-    }
-}
-
-impl TypeOptionBuilder for NumberTypeOptionBuilder {
-    fn field_type(&self) -> FieldType {
-        self.0.field_type()
-    }
-
-    fn entry(&self) -> &dyn TypeOptionDataEntry {
-        &self.0
-    }
-}
-
-// Number
-#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
-pub struct NumberTypeOption {
-    #[pb(index = 1)]
-    pub format: NumberFormat,
-
-    #[pb(index = 2)]
-    pub scale: u32,
-
-    #[pb(index = 3)]
-    pub symbol: String,
-
-    #[pb(index = 4)]
-    pub sign_positive: bool,
-
-    #[pb(index = 5)]
-    pub name: String,
-}
-impl_type_option!(NumberTypeOption, FieldType::Number);
-
-impl CellDataOperation<String, String> for NumberTypeOption {
-    fn decode_cell_data<T>(
-        &self,
-        encoded_data: T,
-        decoded_field_type: &FieldType,
-        _field_meta: &FieldMeta,
-    ) -> FlowyResult<DecodedCellData>
-    where
-        T: Into<String>,
-    {
-        if decoded_field_type.is_date() {
-            return Ok(DecodedCellData::default());
-        }
-
-        let cell_data = encoded_data.into();
-        match self.format {
-            NumberFormat::Number => {
-                if let Ok(v) = cell_data.parse::<f64>() {
-                    return Ok(DecodedCellData::new(v.to_string()));
-                }
-
-                if let Ok(v) = cell_data.parse::<i64>() {
-                    return Ok(DecodedCellData::new(v.to_string()));
-                }
-
-                Ok(DecodedCellData::default())
-            }
-            NumberFormat::Percent => {
-                let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
-                Ok(DecodedCellData::new(content))
-            }
-            _ => {
-                let content = self.money_from_str(&cell_data);
-                Ok(DecodedCellData::new(content))
-            }
-        }
-    }
-
-    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
-    where
-        C: Into<CellContentChangeset>,
-    {
-        let changeset = changeset.into();
-        let mut data = changeset.trim().to_string();
-
-        if self.format != NumberFormat::Number {
-            data = self.strip_symbol(data);
-            if !data.chars().all(char::is_numeric) {
-                return Err(FlowyError::invalid_data().context("Should only contain numbers"));
-            }
-        }
-
-        Ok(data)
-    }
-}
-
-impl std::default::Default for NumberTypeOption {
-    fn default() -> Self {
-        let format = NumberFormat::default();
-        let symbol = format.symbol();
-        NumberTypeOption {
-            format,
-            scale: 0,
-            symbol,
-            sign_positive: true,
-            name: "Number".to_string(),
-        }
-    }
-}
-
-impl NumberTypeOption {
-    pub fn set_format(&mut self, format: NumberFormat) {
-        self.format = format;
-        self.symbol = format.symbol();
-    }
-
-    fn money_from_str(&self, s: &str) -> String {
-        match Decimal::from_str(s) {
-            Ok(mut decimal) => {
-                match decimal.set_scale(self.scale) {
-                    Ok(_) => {}
-                    Err(e) => {
-                        tracing::error!("Set decimal scale failed: {:?}", e);
-                    }
-                }
-
-                decimal.set_sign_positive(self.sign_positive);
-                let money = rusty_money::Money::from_decimal(decimal, self.format.currency());
-                money.to_string()
-            }
-            Err(_) => String::new(),
-        }
-    }
-
-    fn strip_symbol<T: ToString>(&self, s: T) -> String {
-        let mut s = s.to_string();
-        if !s.chars().all(char::is_numeric) {
-            s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
-        }
-        s
-    }
+    pub static ref CURRENCY_SYMBOL: Vec<String> = NumberFormat::iter()
+        .map(|format| format.symbol())
+        .collect::<Vec<String>>();
+    pub static ref STRIP_SYMBOL: Vec<String> = vec![",".to_owned(), ".".to_owned()];
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, EnumIter, Serialize, Deserialize, ProtoBuf_Enum)]
@@ -609,137 +443,3 @@ impl NumberFormat {
         self.currency().symbol.to_string()
     }
 }
-
-fn make_strip_symbol() -> Vec<String> {
-    let mut symbols = vec![",".to_owned(), ".".to_owned()];
-    for format in NumberFormat::iter() {
-        symbols.push(format.symbol());
-    }
-    symbols
-}
-
-#[cfg(test)]
-mod tests {
-    use crate::services::field::FieldBuilder;
-    use crate::services::field::{NumberFormat, NumberTypeOption};
-    use crate::services::row::CellDataOperation;
-    use flowy_grid_data_model::entities::{FieldMeta, FieldType};
-    use strum::IntoEnumIterator;
-
-    #[test]
-    fn number_description_invalid_input_test() {
-        let type_option = NumberTypeOption::default();
-        let field_type = FieldType::Number;
-        let field_meta = FieldBuilder::from_field_type(&field_type).build();
-        assert_equal(&type_option, "", "", &field_type, &field_meta);
-        assert_equal(&type_option, "abc", "", &field_type, &field_meta);
-    }
-
-    #[test]
-    fn number_description_test() {
-        let mut type_option = NumberTypeOption::default();
-        let field_type = FieldType::Number;
-        let field_meta = FieldBuilder::from_field_type(&field_type).build();
-        assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
-        assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
-        assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
-
-        for format in NumberFormat::iter() {
-            type_option.format = format;
-            match format {
-                NumberFormat::Number => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
-                }
-                NumberFormat::USD => {
-                    assert_equal(&type_option, "18443", "$18,443", &field_type, &field_meta);
-                    assert_equal(&type_option, "", "", &field_type, &field_meta);
-                    assert_equal(&type_option, "abc", "", &field_type, &field_meta);
-                }
-                NumberFormat::Yen => {
-                    assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_meta);
-                }
-                NumberFormat::Yuan => {
-                    assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_meta);
-                }
-                NumberFormat::EUR => {
-                    assert_equal(&type_option, "18443", "€18.443", &field_type, &field_meta);
-                }
-                _ => {}
-            }
-        }
-    }
-
-    #[test]
-    fn number_description_scale_test() {
-        let mut type_option = NumberTypeOption {
-            scale: 1,
-            ..Default::default()
-        };
-        let field_type = FieldType::Number;
-        let field_meta = FieldBuilder::from_field_type(&field_type).build();
-
-        for format in NumberFormat::iter() {
-            type_option.format = format;
-            match format {
-                NumberFormat::Number => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
-                }
-                NumberFormat::USD => {
-                    assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
-                }
-                NumberFormat::Yen => {
-                    assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
-                }
-                NumberFormat::EUR => {
-                    assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
-                }
-                _ => {}
-            }
-        }
-    }
-
-    #[test]
-    fn number_description_sign_test() {
-        let mut type_option = NumberTypeOption {
-            sign_positive: false,
-            ..Default::default()
-        };
-        let field_type = FieldType::Number;
-        let field_meta = FieldBuilder::from_field_type(&field_type).build();
-
-        for format in NumberFormat::iter() {
-            type_option.format = format;
-            match format {
-                NumberFormat::Number => {
-                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
-                }
-                NumberFormat::USD => {
-                    assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_meta);
-                }
-                NumberFormat::Yen => {
-                    assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_meta);
-                }
-                NumberFormat::EUR => {
-                    assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_meta);
-                }
-                _ => {}
-            }
-        }
-    }
-
-    fn assert_equal(
-        type_option: &NumberTypeOption,
-        cell_data: &str,
-        expected_str: &str,
-        field_type: &FieldType,
-        field_meta: &FieldMeta,
-    ) {
-        assert_eq!(
-            type_option
-                .decode_cell_data(cell_data, field_type, field_meta)
-                .unwrap()
-                .to_string(),
-            expected_str.to_owned()
-        );
-    }
-}

+ 6 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/mod.rs

@@ -0,0 +1,6 @@
+#![allow(clippy::module_inception)]
+mod format;
+mod number_type_option;
+
+pub use format::*;
+pub use number_type_option::*;

+ 348 - 0
frontend/rust-lib/flowy-grid/src/services/field/type_options/number_type_option/number_type_option.rs

@@ -0,0 +1,348 @@
+use crate::impl_type_option;
+
+use crate::services::field::type_options::number_type_option::format::*;
+use crate::services::field::{BoxTypeOptionBuilder, TypeOptionBuilder};
+use crate::services::row::{CellContentChangeset, CellDataOperation, DecodedCellData};
+use bytes::Bytes;
+use flowy_derive::ProtoBuf;
+use flowy_error::{FlowyError, FlowyResult};
+use flowy_grid_data_model::entities::{
+    CellMeta, FieldMeta, FieldType, TypeOptionDataDeserializer, TypeOptionDataEntry,
+};
+use rust_decimal::Decimal;
+
+use serde::{Deserialize, Serialize};
+use std::str::FromStr;
+
+#[derive(Default)]
+pub struct NumberTypeOptionBuilder(NumberTypeOption);
+impl_into_box_type_option_builder!(NumberTypeOptionBuilder);
+impl_builder_from_json_str_and_from_bytes!(NumberTypeOptionBuilder, NumberTypeOption);
+
+impl NumberTypeOptionBuilder {
+    pub fn name(mut self, name: &str) -> Self {
+        self.0.name = name.to_string();
+        self
+    }
+
+    pub fn set_format(mut self, format: NumberFormat) -> Self {
+        self.0.set_format(format);
+        self
+    }
+
+    pub fn scale(mut self, scale: u32) -> Self {
+        self.0.scale = scale;
+        self
+    }
+
+    pub fn positive(mut self, positive: bool) -> Self {
+        self.0.sign_positive = positive;
+        self
+    }
+}
+
+impl TypeOptionBuilder for NumberTypeOptionBuilder {
+    fn field_type(&self) -> FieldType {
+        self.0.field_type()
+    }
+
+    fn entry(&self) -> &dyn TypeOptionDataEntry {
+        &self.0
+    }
+}
+
+// Number
+#[derive(Clone, Debug, Serialize, Deserialize, ProtoBuf)]
+pub struct NumberTypeOption {
+    #[pb(index = 1)]
+    pub format: NumberFormat,
+
+    #[pb(index = 2)]
+    pub scale: u32,
+
+    #[pb(index = 3)]
+    pub symbol: String,
+
+    #[pb(index = 4)]
+    pub sign_positive: bool,
+
+    #[pb(index = 5)]
+    pub name: String,
+}
+impl_type_option!(NumberTypeOption, FieldType::Number);
+
+impl CellDataOperation<String, String> for NumberTypeOption {
+    fn decode_cell_data<T>(
+        &self,
+        encoded_data: T,
+        decoded_field_type: &FieldType,
+        _field_meta: &FieldMeta,
+    ) -> FlowyResult<DecodedCellData>
+    where
+        T: Into<String>,
+    {
+        if decoded_field_type.is_date() {
+            return Ok(DecodedCellData::default());
+        }
+
+        let cell_data = encoded_data.into();
+        match self.format {
+            NumberFormat::Number => {
+                if let Ok(v) = cell_data.parse::<f64>() {
+                    return Ok(DecodedCellData::new(v.to_string()));
+                }
+
+                if let Ok(v) = cell_data.parse::<i64>() {
+                    return Ok(DecodedCellData::new(v.to_string()));
+                }
+
+                Ok(DecodedCellData::default())
+            }
+            NumberFormat::Percent => {
+                let content = cell_data.parse::<f64>().map_or(String::new(), |v| v.to_string());
+                Ok(DecodedCellData::new(content))
+            }
+            _ => {
+                let content = self.number_from_str(&cell_data);
+                Ok(DecodedCellData::new(content))
+            }
+        }
+    }
+
+    fn apply_changeset<C>(&self, changeset: C, _cell_meta: Option<CellMeta>) -> Result<String, FlowyError>
+    where
+        C: Into<CellContentChangeset>,
+    {
+        let changeset = changeset.into();
+        let mut data = changeset.trim().to_string();
+
+        if self.format != NumberFormat::Number {
+            data = self.strip_symbol(data);
+            if !data.chars().all(char::is_numeric) {
+                return Err(FlowyError::invalid_data().context("Should only contain numbers"));
+            }
+        }
+
+        Ok(data)
+    }
+}
+
+impl std::default::Default for NumberTypeOption {
+    fn default() -> Self {
+        let format = NumberFormat::default();
+        let symbol = format.symbol();
+        NumberTypeOption {
+            format,
+            scale: 0,
+            symbol,
+            sign_positive: true,
+            name: "Number".to_string(),
+        }
+    }
+}
+
+impl NumberTypeOption {
+    pub fn set_format(&mut self, format: NumberFormat) {
+        self.format = format;
+        self.symbol = format.symbol();
+    }
+
+    fn number_from_str(&self, s: &str) -> String {
+        match Decimal::from_str(s) {
+            Ok(mut decimal) => {
+                match decimal.set_scale(self.scale) {
+                    Ok(_) => {}
+                    Err(e) => {
+                        tracing::error!("Set decimal scale failed: {:?}", e);
+                    }
+                }
+
+                decimal.set_sign_positive(self.sign_positive);
+                let money = rusty_money::Money::from_decimal(decimal, self.format.currency());
+                money.to_string()
+            }
+            Err(_) => {
+                let s = self.strip_symbol(s);
+                if !s.is_empty() && s.chars().all(char::is_numeric) {
+                    self.number_from_str(&s)
+                } else {
+                    "".to_owned()
+                }
+            }
+        }
+    }
+
+    fn strip_symbol<T: ToString>(&self, s: T) -> String {
+        let mut s = s.to_string();
+
+        for symbol in CURRENCY_SYMBOL.iter() {
+            if s.starts_with(symbol) {
+                s = s.strip_prefix(symbol).unwrap_or("").to_string();
+                break;
+            }
+        }
+
+        if !s.chars().all(char::is_numeric) {
+            s.retain(|c| !STRIP_SYMBOL.contains(&c.to_string()));
+        }
+        s
+    }
+}
+
+#[cfg(test)]
+mod tests {
+    use crate::services::field::FieldBuilder;
+    use crate::services::field::{NumberFormat, NumberTypeOption};
+    use crate::services::row::CellDataOperation;
+    use flowy_grid_data_model::entities::{FieldMeta, FieldType};
+    use strum::IntoEnumIterator;
+
+    #[test]
+    fn number_type_option_invalid_input_test() {
+        let type_option = NumberTypeOption::default();
+        let field_type = FieldType::Number;
+        let field_meta = FieldBuilder::from_field_type(&field_type).build();
+        assert_equal(&type_option, "", "", &field_type, &field_meta);
+        assert_equal(&type_option, "abc", "", &field_type, &field_meta);
+    }
+
+    #[test]
+    fn number_type_option_format_number_test() {
+        let mut type_option = NumberTypeOption::default();
+        let field_type = FieldType::Number;
+        let field_meta = FieldBuilder::from_field_type(&field_type).build();
+        assert_eq!(type_option.strip_symbol("¥18,443"), "18443".to_owned());
+        assert_eq!(type_option.strip_symbol("$18,443"), "18443".to_owned());
+        assert_eq!(type_option.strip_symbol("€18.443"), "18443".to_owned());
+
+        for format in NumberFormat::iter() {
+            type_option.format = format;
+            match format {
+                NumberFormat::Number => {
+                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
+                }
+                NumberFormat::USD => {
+                    assert_equal(&type_option, "18443", "$18,443", &field_type, &field_meta);
+                }
+                NumberFormat::Yen => {
+                    assert_equal(&type_option, "18443", "¥18,443", &field_type, &field_meta);
+                }
+                NumberFormat::Yuan => {
+                    assert_equal(&type_option, "18443", "CN¥18,443", &field_type, &field_meta);
+                }
+                NumberFormat::EUR => {
+                    assert_equal(&type_option, "18443", "€18.443", &field_type, &field_meta);
+                }
+                _ => {}
+            }
+        }
+    }
+
+    #[test]
+    fn number_type_option_format_str_test() {
+        let mut type_option = NumberTypeOption::default();
+        let field_type = FieldType::Number;
+        let field_meta = FieldBuilder::from_field_type(&field_type).build();
+
+        for format in NumberFormat::iter() {
+            type_option.format = format;
+            match format {
+                NumberFormat::Number => {
+                    // assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
+                }
+                NumberFormat::USD => {
+                    assert_equal(&type_option, "$18,44", "$1,844", &field_type, &field_meta);
+                    assert_equal(&type_option, "", "", &field_type, &field_meta);
+                    assert_equal(&type_option, "abc", "", &field_type, &field_meta);
+                }
+                NumberFormat::Yen => {
+                    assert_equal(&type_option, "¥18,44", "¥1,844", &field_type, &field_meta);
+                    assert_equal(&type_option, "¥1844", "¥1,844", &field_type, &field_meta);
+                }
+                NumberFormat::Yuan => {
+                    assert_equal(&type_option, "CN¥18,44", "CN¥1,844", &field_type, &field_meta);
+                    assert_equal(&type_option, "CN¥1844", "CN¥1,844", &field_type, &field_meta);
+                }
+                NumberFormat::EUR => {
+                    assert_equal(&type_option, "€18.44", "€1.844", &field_type, &field_meta);
+                    assert_equal(&type_option, "€1844", "€1.844", &field_type, &field_meta);
+                }
+                _ => {}
+            }
+        }
+    }
+
+    #[test]
+    fn number_type_option_scale_test() {
+        let mut type_option = NumberTypeOption {
+            scale: 1,
+            ..Default::default()
+        };
+        let field_type = FieldType::Number;
+        let field_meta = FieldBuilder::from_field_type(&field_type).build();
+
+        for format in NumberFormat::iter() {
+            type_option.format = format;
+            match format {
+                NumberFormat::Number => {
+                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
+                }
+                NumberFormat::USD => {
+                    assert_equal(&type_option, "18443", "$1,844.3", &field_type, &field_meta);
+                }
+                NumberFormat::Yen => {
+                    assert_equal(&type_option, "18443", "¥1,844.3", &field_type, &field_meta);
+                }
+                NumberFormat::EUR => {
+                    assert_equal(&type_option, "18443", "€1.844,3", &field_type, &field_meta);
+                }
+                _ => {}
+            }
+        }
+    }
+
+    #[test]
+    fn number_description_sign_test() {
+        let mut type_option = NumberTypeOption {
+            sign_positive: false,
+            ..Default::default()
+        };
+        let field_type = FieldType::Number;
+        let field_meta = FieldBuilder::from_field_type(&field_type).build();
+
+        for format in NumberFormat::iter() {
+            type_option.format = format;
+            match format {
+                NumberFormat::Number => {
+                    assert_equal(&type_option, "18443", "18443", &field_type, &field_meta);
+                }
+                NumberFormat::USD => {
+                    assert_equal(&type_option, "18443", "-$18,443", &field_type, &field_meta);
+                }
+                NumberFormat::Yen => {
+                    assert_equal(&type_option, "18443", "-¥18,443", &field_type, &field_meta);
+                }
+                NumberFormat::EUR => {
+                    assert_equal(&type_option, "18443", "-€18.443", &field_type, &field_meta);
+                }
+                _ => {}
+            }
+        }
+    }
+
+    fn assert_equal(
+        type_option: &NumberTypeOption,
+        cell_data: &str,
+        expected_str: &str,
+        field_type: &FieldType,
+        field_meta: &FieldMeta,
+    ) {
+        assert_eq!(
+            type_option
+                .decode_cell_data(cell_data, field_type, field_meta)
+                .unwrap()
+                .to_string(),
+            expected_str.to_owned()
+        );
+    }
+}