chore: some ui improvements (#2791)

* chore: some ui improvements

* fix: integration test

* feat: language selector on welcome page (#2796)

* feat: add language selector on welcome page

* feat: add hover effect and refactor layout

* test: add basic languge selector testing

* chore: increate place holder width

* fix: add catch error for setLocale and finish the testing

* chore: update comment

* feat: refactor the skip login in page and add tests

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>

* feat: row document (#2792)

* chore: create orphan view handler

* feat: save icon url and cover url in view

* feat: implement emoji picker UI

* chore: config ui

* chore: config ui again

* chore: replace RowPB with RowMetaPB to exposing more row information

* fix: compile error

* feat: show emoji in row

* chore: update

* test: insert emoji test

* test: add update emoji test

* test: add remove emoji test

* test: add create field tests

* test: add create row and delete row integration tests

* test: add create row from row menu

* test: document in row detail page

* test: delete, duplicate row in row detail page

* test: check the row count displayed in grid page

* test: rename existing field in grid page

* test: update field type of exisiting field in grid page

* test: delete field test

* test: add duplicate field test

* test: add hide field test

* test: add edit text cell test

* test: add insert text to text cell test

* test: add edit number cell test

* test: add edit multiple number cells

* test: add edit checkbox cell test

* feat: integrate editor into database row

* test: add edit create time and last edit time cell test

* test: add edit date cell by selecting a date test

* chore: remove unused code

* chore: update checklist bg color

* test: add update database layout test

---------

Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>

* test: fix test

* test: add create select option test

---------

Co-authored-by: Yijing Huang <hyj891204@gmail.com>
Co-authored-by: Lucas.Xu <lucas.xu@appflowy.io>
Co-authored-by: Nathan.fooo <86001920+appflowy@users.noreply.github.com>
Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
Richard Shiue
2023-06-16 15:32:28 +08:00
committed by GitHub
parent 14dee6b797
commit efc857d752
13 changed files with 137 additions and 60 deletions

View File

@ -181,5 +181,30 @@ void main() {
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
testWidgets('edit single select cell', (tester) async {
await tester.initializeAppFlowy();
await tester.tapGoButton();
const fieldType = FieldType.SingleSelect;
await tester.tapAddButton();
// When create a grid, it will create a single select field by default
await tester.tapCreateGridButton();
// Tap the cell to invoke the selection option editor
await tester.tapSelectOptionCellInGrid(rowIndex: 0, fieldType: fieldType);
await tester.findSelectOptionEditor(findsOneWidget);
await tester.createOption(name: 'hello world');
await tester.dismissSelectOptionEditor();
// Make sure the option is created and displayed in the cell
await tester.findSelectOptionWithNameInGrid(
rowIndex: 0,
name: 'hello world',
);
await tester.pumpAndSettle();
});
}); });
} }

View File

@ -71,7 +71,7 @@ void main() {
// The emoji already displayed in the row banner // The emoji already displayed in the row banner
final emojiText = find.byWidgetPredicate( final emojiText = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == '😅', (widget) => widget is FlowyText && widget.text == '😅',
); );
// The number of emoji should be two. One in the row displayed in the grid // The number of emoji should be two. One in the row displayed in the grid
@ -97,7 +97,7 @@ void main() {
// Remove the emoji // Remove the emoji
await tester.tapButton(find.byType(RemoveEmojiButton)); await tester.tapButton(find.byType(RemoveEmojiButton));
final emojiText = find.byWidgetPredicate( final emojiText = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == '😀', (widget) => widget is FlowyText && widget.text == '😀',
); );
expect(emojiText, findsNothing); expect(emojiText, findsNothing);
}); });

View File

@ -104,7 +104,7 @@ extension AppFlowyTestBase on WidgetTester {
); );
if (button.evaluate().isEmpty) { if (button.evaluate().isEmpty) {
button = find.byWidgetPredicate( button = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == tr, (widget) => widget is FlowyText && widget.text == tr,
); );
} }
await tapButton( await tapButton(
@ -135,7 +135,7 @@ extension AppFlowyTestBase on WidgetTester {
extension AppFlowyFinderTestBase on CommonFinders { extension AppFlowyFinderTestBase on CommonFinders {
Finder findTextInFlowyText(String text) { Finder findTextInFlowyText(String text) {
return find.byWidgetPredicate( return find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == text, (widget) => widget is FlowyText && widget.text == text,
); );
} }
} }

View File

@ -14,12 +14,15 @@ import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/disclosure_button.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/filter_menu_item.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/filter/filter_menu_item.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_cell_action_sheet.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_list.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_option_editor.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/filter_button.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_layout.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/toolbar/grid_layout.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/select_option_editor.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/text_field.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database_view/widgets/row/row_document.dart'; import 'package:appflowy/plugins/database_view/widgets/row/row_document.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cells/date_cell/date_editor.dart';
import 'package:appflowy/plugins/database_view/widgets/setting/database_setting.dart'; import 'package:appflowy/plugins/database_view/widgets/setting/database_setting.dart';
@ -37,7 +40,6 @@ import 'package:appflowy/plugins/database_view/grid/presentation/grid_page.dart'
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/footer/grid_footer.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_cell.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_cell.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_editor.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_editor.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/field_type_extension.dart';
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/row/row.dart'; import 'package:appflowy/plugins/database_view/grid/presentation/widgets/row/row.dart';
import 'package:appflowy/plugins/database_view/widgets/row/accessory/cell_accessory.dart'; import 'package:appflowy/plugins/database_view/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database_view/widgets/row/cells/cells.dart'; import 'package:appflowy/plugins/database_view/widgets/row/cells/cells.dart';
@ -255,7 +257,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
matching: find.byWidgetPredicate( matching: find.byWidgetPredicate(
(widget) { (widget) {
if (widget is FlowyText) { if (widget is FlowyText) {
return widget.title == content; return widget.text == content;
} }
return false; return false;
}, },
@ -279,6 +281,59 @@ extension AppFlowyDatabaseTest on WidgetTester {
await tapButton(finder); await tapButton(finder);
} }
Future<void> tapSelectOptionCellInGrid({
required int rowIndex,
required FieldType fieldType,
}) async {
assert(
fieldType == FieldType.SingleSelect || fieldType == FieldType.MultiSelect,
);
final findRow = find.byType(GridRow);
final findCell = finderForFieldType(fieldType);
final cell = find.descendant(
of: findRow.at(rowIndex),
matching: findCell,
);
await tapButton(cell);
}
/// The [SelectOptionCellEditor] must be opened first.
Future<void> createOption({
required String name,
}) async {
final findEditor = find.byType(SelectOptionCellEditor);
expect(findEditor, findsOneWidget);
final findTextField = find.byType(SelectOptionTextField);
expect(findTextField, findsOneWidget);
await enterText(findTextField, name);
await pump();
await testTextInput.receiveAction(TextInputAction.done);
await pumpAndSettle();
}
Future<void> findSelectOptionWithNameInGrid({
required int rowIndex,
required String name,
}) async {
final findRow = find.byType(GridRow);
final option = find.byWidgetPredicate(
(widget) => widget is SelectOptionTag && widget.name == name,
);
final cell = find.descendant(
of: findRow.at(rowIndex),
matching: option,
);
expect(cell, findsOneWidget);
}
Future<void> openFirstRowDetailPage() async { Future<void> openFirstRowDetailPage() async {
await hoverOnFirstRowOfGrid(); await hoverOnFirstRowOfGrid();
@ -410,11 +465,10 @@ extension AppFlowyDatabaseTest on WidgetTester {
/// Must call [tapTypeOptionButton] first. /// Must call [tapTypeOptionButton] first.
Future<void> selectFieldType(FieldType fieldType) async { Future<void> selectFieldType(FieldType fieldType) async {
final fieldTypeCell = find.byType(FieldTypeCell); final fieldTypeCell = find.byType(FieldTypeCell);
final fieldTypeButton = find.descendant( final fieldTypeButton = find.descendant(
of: fieldTypeCell, of: fieldTypeCell,
matching: find.byWidgetPredicate( matching: find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == fieldType.title(), (widget) => widget is FlowyText && widget.text == fieldType.title(),
), ),
); );
await tapButton(fieldTypeButton); await tapButton(fieldTypeButton);
@ -493,6 +547,16 @@ extension AppFlowyDatabaseTest on WidgetTester {
expect(finder, matcher); expect(finder, matcher);
} }
Future<void> findSelectOptionEditor(dynamic matcher) async {
final finder = find.byType(SelectOptionCellEditor);
expect(finder, matcher);
}
Future<void> dismissSelectOptionEditor() async {
await sendKeyEvent(LogicalKeyboardKey.escape);
await pumpAndSettle();
}
Future<void> tapCreateRowButtonInGrid() async { Future<void> tapCreateRowButtonInGrid() async {
await tapButton(find.byType(GridAddRowButton)); await tapButton(find.byType(GridAddRowButton));
} }
@ -512,7 +576,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
Future<void> assertRowCountInGridPage(int num) async { Future<void> assertRowCountInGridPage(int num) async {
final text = find.byWidgetPredicate( final text = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == rowCountString(num), (widget) => widget is FlowyText && widget.text == rowCountString(num),
); );
expect(text, findsOneWidget); expect(text, findsOneWidget);
} }
@ -653,7 +717,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
final findLayoutButton = find.byWidgetPredicate( final findLayoutButton = find.byWidgetPredicate(
(widget) => (widget) =>
widget is FlowyText && widget is FlowyText &&
widget.title == DatabaseSettingAction.showLayout.title(), widget.text == DatabaseSettingAction.showLayout.title(),
); );
final button = find.descendant( final button = find.descendant(
@ -667,7 +731,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
Future<void> selectDatabaseLayoutType(DatabaseLayoutPB layout) async { Future<void> selectDatabaseLayoutType(DatabaseLayoutPB layout) async {
final findLayoutCell = find.byType(DatabaseViewLayoutCell); final findLayoutCell = find.byType(DatabaseViewLayoutCell);
final findText = find.byWidgetPredicate( final findText = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == layout.layoutName(), (widget) => widget is FlowyText && widget.text == layout.layoutName(),
); );
final button = find.descendant( final button = find.descendant(

View File

@ -12,7 +12,7 @@ extension Expectation on WidgetTester {
/// Expect to see the home page and with a default read me page. /// Expect to see the home page and with a default read me page.
void expectToSeeHomePage() { void expectToSeeHomePage() {
expect(find.byType(HomeStack), findsOneWidget); expect(find.byType(HomeStack), findsOneWidget);
expect(find.textContaining(readme), findsOneWidget); expect(find.textContaining(readme), findsWidgets);
} }
/// Expect to see the page name on the home page. /// Expect to see the page name on the home page.
@ -42,7 +42,7 @@ extension Expectation on WidgetTester {
final exportSuccess = find.byWidgetPredicate( final exportSuccess = find.byWidgetPredicate(
(widget) => (widget) =>
widget is FlowyText && widget is FlowyText &&
widget.title == LocaleKeys.settings_files_exportFileSuccess.tr(), widget.text == LocaleKeys.settings_files_exportFileSuccess.tr(),
); );
expect(exportSuccess, findsOneWidget); expect(exportSuccess, findsOneWidget);
} }
@ -62,7 +62,7 @@ extension Expectation on WidgetTester {
/// Expect to see the user name on the home page /// Expect to see the user name on the home page
void expectToSeeUserName(String name) { void expectToSeeUserName(String name) {
final userName = find.byWidgetPredicate( final userName = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == name, (widget) => widget is FlowyText && widget.text == name,
); );
expect(userName, findsOneWidget); expect(userName, findsOneWidget);
} }
@ -72,7 +72,7 @@ extension Expectation on WidgetTester {
Finder textWidget = find.textContaining(text, findRichText: true); Finder textWidget = find.textContaining(text, findRichText: true);
if (textWidget.evaluate().isEmpty) { if (textWidget.evaluate().isEmpty) {
textWidget = find.byWidgetPredicate( textWidget = find.byWidgetPredicate(
(widget) => widget is FlowyText && widget.title == text, (widget) => widget is FlowyText && widget.text == text,
); );
} }
expect(textWidget, findsOneWidget); expect(textWidget, findsOneWidget);

View File

@ -169,17 +169,14 @@ class FieldActionCell extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
return FlowyButton( return FlowyButton(
hoverColor: AFThemeExtension.of(context).lightGreyHover, hoverColor: AFThemeExtension.of(context).lightGreyHover,
disable: !enable,
text: FlowyText.medium( text: FlowyText.medium(
action.title(), action.title(),
color: enable color: enable
? AFThemeExtension.of(context).textColor ? AFThemeExtension.of(context).textColor
: Theme.of(context).disabledColor, : Theme.of(context).disabledColor,
), ),
onTap: () { onTap: () => action.run(context, fieldInfo),
if (enable) {
action.run(context, fieldInfo);
}
},
leftIcon: svgWidget( leftIcon: svgWidget(
action.iconName(), action.iconName(),
color: enable color: enable

View File

@ -3,6 +3,7 @@ import 'package:appflowy/plugins/database_view/application/field/type_option/typ
import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:dartz/dartz.dart' show none; import 'package:dartz/dartz.dart' show none;
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra_ui/style_widget/button.dart'; import 'package:flowy_infra_ui/style_widget/button.dart';
import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text.dart';
import 'package:flowy_infra_ui/style_widget/text_field.dart'; import 'package:flowy_infra_ui/style_widget/text_field.dart';
@ -232,15 +233,16 @@ class _DeleteFieldButton extends StatelessWidget {
LocaleKeys.grid_field_delete.tr(), LocaleKeys.grid_field_delete.tr(),
color: enable ? null : Theme.of(context).disabledColor, color: enable ? null : Theme.of(context).disabledColor,
), ),
leftIcon: svgWidget(
'grid/delete',
color: enable ? null : Theme.of(context).disabledColor,
),
onTap: () { onTap: () {
if (enable) onDeleted?.call(); if (enable) onDeleted?.call();
}, },
onHover: (_) => popoverMutex.close(), onHover: (_) => popoverMutex.close(),
); );
return Padding( return SizedBox(height: GridSize.popoverItemHeight, child: button);
padding: const EdgeInsets.only(bottom: 4.0),
child: SizedBox(height: GridSize.popoverItemHeight, child: button),
);
}, },
); );
} }
@ -265,13 +267,11 @@ class _HideFieldButton extends StatelessWidget {
text: FlowyText.medium( text: FlowyText.medium(
LocaleKeys.grid_field_hide.tr(), LocaleKeys.grid_field_hide.tr(),
), ),
leftIcon: svgWidget('grid/hide'),
onTap: () => onHidden?.call(), onTap: () => onHidden?.call(),
onHover: (_) => popoverMutex.close(), onHover: (_) => popoverMutex.close(),
); );
return Padding( return SizedBox(height: GridSize.popoverItemHeight, child: button);
padding: const EdgeInsets.only(bottom: 4.0),
child: SizedBox(height: GridSize.popoverItemHeight, child: button),
);
}, },
); );
} }

View File

@ -115,7 +115,6 @@ class SwitchFieldButton extends StatelessWidget {
text: FlowyText.medium( text: FlowyText.medium(
bloc.state.field.fieldType.title(), bloc.state.field.fieldType.title(),
), ),
margin: GridSize.typeOptionContentInsets,
leftIcon: FlowySvg(name: bloc.state.field.fieldType.iconName()), leftIcon: FlowySvg(name: bloc.state.field.fieldType.iconName()),
rightIcon: const FlowySvg(name: 'grid/more'), rightIcon: const FlowySvg(name: 'grid/more'),
); );

View File

@ -93,11 +93,9 @@ class DateTypeOptionWidget extends TypeOptionWidget {
}, },
); );
}, },
child: Padding( child: const Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: EdgeInsets.symmetric(horizontal: 12.0),
child: DateFormatButton( child: DateFormatButton(),
buttonMargins: GridSize.typeOptionContentInsets,
),
), ),
); );
} }
@ -125,10 +123,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
}, },
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: TimeFormatButton( child: TimeFormatButton(timeFormat: timeFormat),
timeFormat: timeFormat,
buttonMargins: GridSize.typeOptionContentInsets,
),
), ),
); );
} }
@ -137,11 +132,9 @@ class DateTypeOptionWidget extends TypeOptionWidget {
class DateFormatButton extends StatelessWidget { class DateFormatButton extends StatelessWidget {
final VoidCallback? onTap; final VoidCallback? onTap;
final void Function(bool)? onHover; final void Function(bool)? onHover;
final EdgeInsets? buttonMargins;
const DateFormatButton({ const DateFormatButton({
this.onTap, this.onTap,
this.onHover, this.onHover,
this.buttonMargins,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -151,7 +144,6 @@ class DateFormatButton extends StatelessWidget {
height: GridSize.popoverItemHeight, height: GridSize.popoverItemHeight,
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr()), text: FlowyText.medium(LocaleKeys.grid_field_dateFormat.tr()),
margin: buttonMargins,
onTap: onTap, onTap: onTap,
onHover: onHover, onHover: onHover,
rightIcon: const FlowySvg(name: 'grid/more'), rightIcon: const FlowySvg(name: 'grid/more'),
@ -164,12 +156,10 @@ class TimeFormatButton extends StatelessWidget {
final TimeFormatPB timeFormat; final TimeFormatPB timeFormat;
final VoidCallback? onTap; final VoidCallback? onTap;
final void Function(bool)? onHover; final void Function(bool)? onHover;
final EdgeInsets? buttonMargins;
const TimeFormatButton({ const TimeFormatButton({
required this.timeFormat, required this.timeFormat,
this.onTap, this.onTap,
this.onHover, this.onHover,
this.buttonMargins,
Key? key, Key? key,
}) : super(key: key); }) : super(key: key);
@ -179,7 +169,6 @@ class TimeFormatButton extends StatelessWidget {
height: GridSize.popoverItemHeight, height: GridSize.popoverItemHeight,
child: FlowyButton( child: FlowyButton(
text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr()), text: FlowyText.medium(LocaleKeys.grid_field_timeFormat.tr()),
margin: buttonMargins,
onTap: onTap, onTap: onTap,
onHover: onHover, onHover: onHover,
rightIcon: const FlowySvg(name: 'grid/more'), rightIcon: const FlowySvg(name: 'grid/more'),

View File

@ -209,7 +209,7 @@ class _OptionCellState extends State<_OptionCell> {
offset: const Offset(8, 0), offset: const Offset(8, 0),
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
asBarrier: true, asBarrier: true,
constraints: BoxConstraints.loose(const Size(460, 460)), constraints: BoxConstraints.loose(const Size(460, 470)),
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),
child: child, child: child,

View File

@ -337,7 +337,7 @@ class _SelectOptionCellState extends State<_SelectOptionCell> {
offset: const Offset(8, 0), offset: const Offset(8, 0),
margin: EdgeInsets.zero, margin: EdgeInsets.zero,
asBarrier: true, asBarrier: true,
constraints: BoxConstraints.loose(const Size(200, 460)), constraints: BoxConstraints.loose(const Size(200, 470)),
mutex: widget.popoverMutex, mutex: widget.popoverMutex,
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 12.0), padding: const EdgeInsets.symmetric(horizontal: 12.0),

View File

@ -56,7 +56,13 @@ class FlowyButton extends StatelessWidget {
), ),
); );
} else { } else {
return Opacity(opacity: disableOpacity, child: _render()); return Opacity(
opacity: disableOpacity,
child: MouseRegion(
cursor: SystemMouseCursors.forbidden,
child: _render(),
),
);
} }
} }

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
class FlowyText extends StatelessWidget { class FlowyText extends StatelessWidget {
final String title; final String text;
final TextOverflow? overflow; final TextOverflow? overflow;
final double? fontSize; final double? fontSize;
final FontWeight? fontWeight; final FontWeight? fontWeight;
@ -13,8 +13,7 @@ class FlowyText extends StatelessWidget {
final String? fontFamily; final String? fontFamily;
const FlowyText( const FlowyText(
this.title, { this.text, {
Key? key,
this.overflow = TextOverflow.clip, this.overflow = TextOverflow.clip,
this.fontSize, this.fontSize,
this.fontWeight, this.fontWeight,
@ -24,11 +23,11 @@ class FlowyText extends StatelessWidget {
this.decoration, this.decoration,
this.selectable = false, this.selectable = false,
this.fontFamily, this.fontFamily,
Key? key,
}) : super(key: key); }) : super(key: key);
const FlowyText.regular( const FlowyText.regular(
this.title, { this.text, {
Key? key,
this.fontSize, this.fontSize,
this.overflow, this.overflow,
this.color, this.color,
@ -37,12 +36,12 @@ class FlowyText extends StatelessWidget {
this.decoration, this.decoration,
this.selectable = false, this.selectable = false,
this.fontFamily, this.fontFamily,
Key? key,
}) : fontWeight = FontWeight.w400, }) : fontWeight = FontWeight.w400,
super(key: key); super(key: key);
const FlowyText.medium( const FlowyText.medium(
this.title, { this.text, {
Key? key,
this.fontSize, this.fontSize,
this.overflow, this.overflow,
this.color, this.color,
@ -51,12 +50,12 @@ class FlowyText extends StatelessWidget {
this.decoration, this.decoration,
this.selectable = false, this.selectable = false,
this.fontFamily, this.fontFamily,
Key? key,
}) : fontWeight = FontWeight.w500, }) : fontWeight = FontWeight.w500,
super(key: key); super(key: key);
const FlowyText.semibold( const FlowyText.semibold(
this.title, { this.text, {
Key? key,
this.fontSize, this.fontSize,
this.overflow, this.overflow,
this.color, this.color,
@ -65,14 +64,12 @@ class FlowyText extends StatelessWidget {
this.decoration, this.decoration,
this.selectable = false, this.selectable = false,
this.fontFamily, this.fontFamily,
Key? key,
}) : fontWeight = FontWeight.w600, }) : fontWeight = FontWeight.w600,
super(key: key); super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final text = overflow == TextOverflow.ellipsis
? title.replaceAll('', '\u200B')
: title;
if (selectable) { if (selectable) {
return SelectableText( return SelectableText(
text, text,