diff --git a/frontend/app_flowy/assets/translations/en.json b/frontend/app_flowy/assets/translations/en.json index 23ee45d008..fb4c5f2e73 100644 --- a/frontend/app_flowy/assets/translations/en.json +++ b/frontend/app_flowy/assets/translations/en.json @@ -40,6 +40,12 @@ "markdown": "Markdown", "copyLink": "Copy Link" }, + "moreAction": { + "small": "small", + "medium": "medium", + "large": "large", + "fontSize": "Font Size" + }, "disclosureAction": { "rename": "Rename", "delete": "Delete", diff --git a/frontend/app_flowy/lib/plugins/document/document.dart b/frontend/app_flowy/lib/plugins/document/document.dart index 5d695ff83e..b3950b9380 100644 --- a/frontend/app_flowy/lib/plugins/document/document.dart +++ b/frontend/app_flowy/lib/plugins/document/document.dart @@ -1,29 +1,19 @@ library document_plugin; import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/plugins/document/document_page.dart'; +import 'package:app_flowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; +import 'package:app_flowy/plugins/document/presentation/more/more_button.dart'; +import 'package:app_flowy/plugins/document/presentation/share/share_button.dart'; import 'package:app_flowy/plugins/util.dart'; import 'package:app_flowy/startup/plugin/plugin.dart'; -import 'package:app_flowy/startup/startup.dart'; -import 'package:app_flowy/plugins/document/application/share_bloc.dart'; import 'package:app_flowy/workspace/presentation/home/home_stack.dart'; -import 'package:app_flowy/workspace/presentation/home/toast.dart'; import 'package:app_flowy/workspace/presentation/widgets/left_bar_item.dart'; -import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; -import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; -import 'package:appflowy_popover/appflowy_popover.dart'; -import 'package:clipboard/clipboard.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:file_picker/file_picker.dart'; -import 'package:flowy_infra_ui/widget/rounded_button.dart'; -import 'package:flowy_sdk/log.dart'; -import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; -import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'document_page.dart'; - class DocumentPluginBuilder extends PluginBuilder { @override Plugin build(dynamic data) { @@ -49,6 +39,8 @@ class DocumentPluginBuilder extends PluginBuilder { class DocumentPlugin extends Plugin { late PluginType _pluginType; + final DocumentAppearanceCubit _documentAppearanceCubit = + DocumentAppearanceCubit(); @override final ViewPluginNotifier notifier; @@ -59,10 +51,22 @@ class DocumentPlugin extends Plugin { Key? key, }) : notifier = ViewPluginNotifier(view: view) { _pluginType = pluginType; + _documentAppearanceCubit.fetch(); } @override - PluginDisplay get display => DocumentPluginDisplay(notifier: notifier); + void dispose() { + _documentAppearanceCubit.close(); + super.dispose(); + } + + @override + PluginDisplay get display { + return DocumentPluginDisplay( + notifier: notifier, + documentAppearanceCubit: _documentAppearanceCubit, + ); + } @override PluginType get ty => _pluginType; @@ -75,8 +79,13 @@ class DocumentPluginDisplay extends PluginDisplay with NavigationItem { final ViewPluginNotifier notifier; ViewPB get view => notifier.view; int? deletedViewIndex; + DocumentAppearanceCubit documentAppearanceCubit; - DocumentPluginDisplay({required this.notifier, Key? key}); + DocumentPluginDisplay({ + required this.notifier, + required this.documentAppearanceCubit, + Key? key, + }); @override Widget buildWidget(PluginContext context) { @@ -88,10 +97,17 @@ class DocumentPluginDisplay extends PluginDisplay with NavigationItem { }); }); - return DocumentPage( - view: view, - onDeleted: () => context.onDeleted(view, deletedViewIndex), - key: ValueKey(view.id), + return BlocProvider.value( + value: documentAppearanceCubit, + child: BlocBuilder( + builder: (_, state) { + return DocumentPage( + view: view, + onDeleted: () => context.onDeleted(view, deletedViewIndex), + key: ValueKey(view.id), + ); + }, + ), ); } @@ -99,133 +115,19 @@ class DocumentPluginDisplay extends PluginDisplay with NavigationItem { Widget get leftBarItem => ViewLeftBarItem(view: view); @override - Widget? get rightBarItem => DocumentShareButton(view: view); + Widget? get rightBarItem { + return Row( + children: [ + DocumentShareButton(view: view), + const SizedBox(width: 10), + BlocProvider.value( + value: documentAppearanceCubit, + child: const DocumentMoreButton(), + ), + ], + ); + } @override List get navigationItems => [this]; } - -class DocumentShareButton extends StatelessWidget { - final ViewPB view; - DocumentShareButton({Key? key, required this.view}) - : super(key: ValueKey(view.hashCode)); - - @override - Widget build(BuildContext context) { - return BlocProvider( - create: (context) => getIt(param1: view), - child: BlocListener( - listener: (context, state) { - state.map( - initial: (_) {}, - loading: (_) {}, - finish: (state) { - state.successOrFail.fold( - _handleExportData, - _handleExportError, - ); - }, - ); - }, - child: BlocBuilder( - builder: (context, state) => ConstrainedBox( - constraints: const BoxConstraints.expand( - height: 30, - width: 100, - ), - child: ShareActionList(view: view), - ), - ), - ), - ); - } - - void _handleExportData(ExportDataPB exportData) { - switch (exportData.exportType) { - case ExportType.Link: - break; - case ExportType.Markdown: - FlutterClipboard.copy(exportData.data) - .then((value) => Log.info('copied to clipboard')); - break; - case ExportType.Text: - break; - } - } - - void _handleExportError(FlowyError error) {} -} - -class ShareActionList extends StatelessWidget { - const ShareActionList({ - Key? key, - required this.view, - }) : super(key: key); - - final ViewPB view; - - @override - Widget build(BuildContext context) { - final docShareBloc = context.read(); - return PopoverActionList( - direction: PopoverDirection.bottomWithCenterAligned, - actions: ShareAction.values - .map((action) => ShareActionWrapper(action)) - .toList(), - buildChild: (controller) { - return RoundedTextButton( - title: LocaleKeys.shareAction_buttonText.tr(), - onPressed: () => controller.show(), - ); - }, - onSelected: (action, controller) async { - switch (action.inner) { - case ShareAction.markdown: - final exportPath = await FilePicker.platform.saveFile( - dialogTitle: '', - fileName: '${view.name}.md', - ); - if (exportPath != null) { - docShareBloc.add(DocShareEvent.shareMarkdown(exportPath)); - showMessageToast('Exported to: $exportPath'); - } - break; - case ShareAction.copyLink: - NavigatorAlertDialog( - title: LocaleKeys.shareAction_workInProgress.tr()) - .show(context); - break; - } - controller.close(); - }, - ); - } -} - -enum ShareAction { - markdown, - copyLink, -} - -class ShareActionWrapper extends ActionCell { - final ShareAction inner; - - ShareActionWrapper(this.inner); - - @override - Widget? leftIcon(Color iconColor) => null; - - @override - String get name => inner.name; -} - -extension QuestionBubbleExtension on ShareAction { - String get name { - switch (this) { - case ShareAction.markdown: - return LocaleKeys.shareAction_markdown.tr(); - case ShareAction.copyLink: - return LocaleKeys.shareAction_copyLink.tr(); - } - } -} diff --git a/frontend/app_flowy/lib/plugins/document/editor_styles.dart b/frontend/app_flowy/lib/plugins/document/editor_styles.dart index 0468542a51..9ff3aca30d 100644 --- a/frontend/app_flowy/lib/plugins/document/editor_styles.dart +++ b/frontend/app_flowy/lib/plugins/document/editor_styles.dart @@ -1,9 +1,11 @@ +import 'package:app_flowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flutter/material.dart'; - -const _baseFontSize = 14.0; +import 'package:provider/provider.dart'; EditorStyle customEditorTheme(BuildContext context) { + final documentStyle = + context.watch().documentAppearance; var editorStyle = Theme.of(context).brightness == Brightness.dark ? EditorStyle.dark : EditorStyle.light; @@ -11,14 +13,15 @@ EditorStyle customEditorTheme(BuildContext context) { padding: const EdgeInsets.all(0), textStyle: editorStyle.textStyle?.copyWith( fontFamily: 'poppins', - fontSize: _baseFontSize, + fontSize: documentStyle.fontSize, ), placeholderTextStyle: editorStyle.placeholderTextStyle?.copyWith( fontFamily: 'poppins', - fontSize: _baseFontSize, + fontSize: documentStyle.fontSize, ), bold: editorStyle.bold?.copyWith( - fontWeight: FontWeight.w500, + fontWeight: FontWeight.w600, + fontFamily: 'poppins-Bold', ), backgroundColor: Theme.of(context).colorScheme.surface, ); @@ -26,6 +29,9 @@ EditorStyle customEditorTheme(BuildContext context) { } Iterable> customPluginTheme(BuildContext context) { + final documentStyle = + context.watch().documentAppearance; + final baseFontSize = documentStyle.fontSize; const basePadding = 12.0; var headingPluginStyle = Theme.of(context).brightness == Brightness.dark ? HeadingPluginStyle.dark @@ -33,15 +39,15 @@ Iterable> customPluginTheme(BuildContext context) { headingPluginStyle = headingPluginStyle.copyWith( textStyle: (EditorState editorState, Node node) { final headingToFontSize = { - 'h1': _baseFontSize + 12, - 'h2': _baseFontSize + 8, - 'h3': _baseFontSize + 4, - 'h4': _baseFontSize, - 'h5': _baseFontSize, - 'h6': _baseFontSize, + 'h1': baseFontSize + 12, + 'h2': baseFontSize + 8, + 'h3': baseFontSize + 4, + 'h4': baseFontSize, + 'h5': baseFontSize, + 'h6': baseFontSize, }; final fontSize = - headingToFontSize[node.attributes.heading] ?? _baseFontSize; + headingToFontSize[node.attributes.heading] ?? baseFontSize; return TextStyle(fontSize: fontSize, fontWeight: FontWeight.w600); }, padding: (EditorState editorState, Node node) { @@ -57,10 +63,28 @@ Iterable> customPluginTheme(BuildContext context) { return EdgeInsets.only(bottom: padding); }, ); + var numberListPluginStyle = Theme.of(context).brightness == Brightness.dark + ? NumberListPluginStyle.dark + : NumberListPluginStyle.light; + + numberListPluginStyle = numberListPluginStyle.copyWith( + icon: (_, textNode) { + const iconPadding = EdgeInsets.only(left: 5.0, right: 5.0); + return Container( + padding: iconPadding, + child: Text( + '${textNode.attributes.number.toString()}.', + style: customEditorTheme(context).textStyle, + ), + ); + }, + ); final pluginTheme = Theme.of(context).brightness == Brightness.dark ? darkPlguinStyleExtension : lightPlguinStyleExtension; return pluginTheme.toList() - ..removeWhere((element) => element is HeadingPluginStyle) - ..add(headingPluginStyle); + ..removeWhere((element) => + element is HeadingPluginStyle || element is NumberListPluginStyle) + ..add(headingPluginStyle) + ..add(numberListPluginStyle); } diff --git a/frontend/app_flowy/lib/plugins/document/presentation/more/cubit/document_appearance_cubit.dart b/frontend/app_flowy/lib/plugins/document/presentation/more/cubit/document_appearance_cubit.dart new file mode 100644 index 0000000000..61d50673f1 --- /dev/null +++ b/frontend/app_flowy/lib/plugins/document/presentation/more/cubit/document_appearance_cubit.dart @@ -0,0 +1,40 @@ +import 'package:bloc/bloc.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +const String _kDocumentAppearenceFontSize = 'kDocumentAppearenceFontSize'; + +class DocumentAppearance { + const DocumentAppearance({ + required this.fontSize, + }); + + final double fontSize; + // Will be supported... + // final String fontName; + + DocumentAppearance copyWith({double? fontSize}) { + return DocumentAppearance( + fontSize: fontSize ?? this.fontSize, + ); + } +} + +class DocumentAppearanceCubit extends Cubit { + DocumentAppearanceCubit() : super(const DocumentAppearance(fontSize: 14.0)); + + late DocumentAppearance documentAppearance; + + void fetch() async { + final prefs = await SharedPreferences.getInstance(); + final fontSize = prefs.getDouble(_kDocumentAppearenceFontSize) ?? 14.0; + documentAppearance = DocumentAppearance(fontSize: fontSize); + emit(documentAppearance); + } + + void sync(DocumentAppearance documentAppearance) async { + final prefs = await SharedPreferences.getInstance(); + prefs.setDouble(_kDocumentAppearenceFontSize, documentAppearance.fontSize); + this.documentAppearance = documentAppearance; + emit(documentAppearance); + } +} diff --git a/frontend/app_flowy/lib/plugins/document/presentation/more/font_size_switcher.dart b/frontend/app_flowy/lib/plugins/document/presentation/more/font_size_switcher.dart new file mode 100644 index 0000000000..b07dcfe5ed --- /dev/null +++ b/frontend/app_flowy/lib/plugins/document/presentation/more/font_size_switcher.dart @@ -0,0 +1,89 @@ +import 'package:app_flowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; +import 'package:flowy_infra_ui/style_widget/text.dart'; +import 'package:flutter/material.dart'; +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:provider/provider.dart'; +import 'package:tuple/tuple.dart'; +import 'package:easy_localization/easy_localization.dart'; + +class FontSizeSwitcher extends StatefulWidget { + const FontSizeSwitcher({ + super.key, + }); + + @override + State createState() => _FontSizeSwitcherState(); +} + +class _FontSizeSwitcherState extends State { + final List _selectedFontSizes = [false, true, false]; + final List> _fontSizes = [ + Tuple2(LocaleKeys.moreAction_small.tr(), 12.0), + Tuple2(LocaleKeys.moreAction_medium.tr(), 14.0), + Tuple2(LocaleKeys.moreAction_large.tr(), 18.0), + ]; + + @override + void initState() { + super.initState(); + + final fontSize = + context.read().documentAppearance.fontSize; + final index = _fontSizes.indexWhere((element) => element.item2 == fontSize); + _updateSelectedFontSize(index); + } + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + FlowyText.semibold( + LocaleKeys.moreAction_fontSize.tr(), + fontSize: 12, + ), + const SizedBox( + height: 5, + ), + ToggleButtons( + isSelected: _selectedFontSizes, + onPressed: (int index) { + _updateSelectedFontSize(index); + _sync(index); + }, + borderRadius: const BorderRadius.all(Radius.circular(5)), + selectedBorderColor: Theme.of(context).colorScheme.primaryContainer, + selectedColor: Theme.of(context).colorScheme.onSurface, + fillColor: Theme.of(context).colorScheme.primaryContainer, + color: Theme.of(context).hintColor, + constraints: const BoxConstraints( + minHeight: 40.0, + minWidth: 80.0, + ), + children: _fontSizes + .map((e) => Text( + e.item1, + style: TextStyle(fontSize: e.item2), + )) + .toList(), + ), + ], + ); + } + + void _updateSelectedFontSize(int index) { + setState(() { + for (int i = 0; i < _selectedFontSizes.length; i++) { + _selectedFontSizes[i] = i == index; + } + }); + } + + void _sync(int index) { + if (index < 0 || index >= _fontSizes.length) return; + final fontSize = _fontSizes[index].item2; + final cubit = context.read(); + final documentAppearance = cubit.documentAppearance; + cubit.sync(documentAppearance.copyWith(fontSize: fontSize)); + } +} diff --git a/frontend/app_flowy/lib/plugins/document/presentation/more/more_button.dart b/frontend/app_flowy/lib/plugins/document/presentation/more/more_button.dart new file mode 100644 index 0000000000..3f1ec921df --- /dev/null +++ b/frontend/app_flowy/lib/plugins/document/presentation/more/more_button.dart @@ -0,0 +1,35 @@ +import 'package:app_flowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; +import 'package:app_flowy/plugins/document/presentation/more/font_size_switcher.dart'; +import 'package:flowy_infra/image.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class DocumentMoreButton extends StatelessWidget { + const DocumentMoreButton({ + Key? key, + }) : super(key: key); + + @override + Widget build(BuildContext context) { + return PopupMenuButton( + offset: const Offset(0, 30), + itemBuilder: (context) { + return [ + PopupMenuItem( + value: 1, + enabled: false, + child: BlocProvider.value( + value: context.read(), + child: const FontSizeSwitcher(), + ), + ) + ]; + }, + child: svgWidget( + 'editor/details', + size: const Size(18, 18), + color: Theme.of(context).colorScheme.onSurface, + ), + ); + } +} diff --git a/frontend/app_flowy/lib/plugins/document/presentation/share/share_button.dart b/frontend/app_flowy/lib/plugins/document/presentation/share/share_button.dart new file mode 100644 index 0000000000..c56b70155e --- /dev/null +++ b/frontend/app_flowy/lib/plugins/document/presentation/share/share_button.dart @@ -0,0 +1,132 @@ +library document_plugin; + +import 'package:app_flowy/generated/locale_keys.g.dart'; +import 'package:app_flowy/startup/startup.dart'; +import 'package:app_flowy/plugins/document/application/share_bloc.dart'; +import 'package:app_flowy/workspace/presentation/home/toast.dart'; +import 'package:app_flowy/workspace/presentation/widgets/dialogs.dart'; +import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:clipboard/clipboard.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:file_picker/file_picker.dart'; +import 'package:flowy_infra_ui/widget/rounded_button.dart'; +import 'package:flowy_sdk/log.dart'; +import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart'; +import 'package:flowy_sdk/protobuf/flowy-document/entities.pb.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; + +class DocumentShareButton extends StatelessWidget { + final ViewPB view; + DocumentShareButton({Key? key, required this.view}) + : super(key: ValueKey(view.hashCode)); + + @override + Widget build(BuildContext context) { + return BlocProvider( + create: (context) => getIt(param1: view), + child: BlocListener( + listener: (context, state) { + state.map( + initial: (_) {}, + loading: (_) {}, + finish: (state) { + state.successOrFail.fold( + _handleExportData, + _handleExportError, + ); + }, + ); + }, + child: BlocBuilder( + builder: (context, state) => ConstrainedBox( + constraints: const BoxConstraints.expand( + height: 30, + width: 100, + ), + child: ShareActionList(view: view), + ), + ), + ), + ); + } + + void _handleExportData(ExportDataPB exportData) { + switch (exportData.exportType) { + case ExportType.Link: + break; + case ExportType.Markdown: + FlutterClipboard.copy(exportData.data) + .then((value) => Log.info('copied to clipboard')); + break; + case ExportType.Text: + break; + } + } + + void _handleExportError(FlowyError error) {} +} + +class ShareActionList extends StatelessWidget { + const ShareActionList({ + Key? key, + required this.view, + }) : super(key: key); + + final ViewPB view; + + @override + Widget build(BuildContext context) { + final docShareBloc = context.read(); + return PopoverActionList( + direction: PopoverDirection.bottomWithCenterAligned, + actions: ShareAction.values + .map((action) => ShareActionWrapper(action)) + .toList(), + buildChild: (controller) { + return RoundedTextButton( + title: LocaleKeys.shareAction_buttonText.tr(), + onPressed: () => controller.show(), + ); + }, + onSelected: (action, controller) async { + switch (action.inner) { + case ShareAction.markdown: + final exportPath = await FilePicker.platform.saveFile( + dialogTitle: '', + fileName: '${view.name}.md', + ); + if (exportPath != null) { + docShareBloc.add(DocShareEvent.shareMarkdown(exportPath)); + showMessageToast('Exported to: $exportPath'); + } + break; + case ShareAction.copyLink: + NavigatorAlertDialog( + title: LocaleKeys.shareAction_workInProgress.tr()) + .show(context); + break; + } + controller.close(); + }, + ); + } +} + +enum ShareAction { + markdown, + copyLink, +} + +class ShareActionWrapper extends ActionCell { + final ShareAction inner; + + ShareActionWrapper(this.inner); + + Widget? icon(Color iconColor) => null; + + @override + String get name => inner.name; +} diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/checkbox_text.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/checkbox_text.dart index a2e0aa5d32..90c2eb3fb4 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/checkbox_text.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/checkbox_text.dart @@ -84,6 +84,7 @@ class _CheckboxNodeWidgetState extends State GestureDetector( key: iconKey, child: icon, + behavior: HitTestBehavior.opaque, onTap: () async { await widget.editorState.formatTextToCheckbox( widget.editorState, diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart index f48714045b..b739211951 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/rich_text/rich_text.dart @@ -72,7 +72,7 @@ class _RichTextNodeWidgetState extends State child: FlowyRichText( key: _richTextKey, textNode: widget.textNode, - textSpanDecorator: (textSpan) => textSpan.updateTextStyle(textStyle), + textSpanDecorator: (textSpan) => textSpan, placeholderTextSpanDecorator: (textSpan) => textSpan.updateTextStyle(textStyle), lineHeight: widget.editorState.editorStyle.lineHeight, diff --git a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart index 5ab7f6cc50..b6051f4877 100644 --- a/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart +++ b/frontend/app_flowy/packages/appflowy_editor/lib/src/render/toolbar/toolbar_item.dart @@ -255,7 +255,9 @@ List defaultToolbarItems = [ highlightCallback: (editorState) => _allSatisfy( editorState, BuiltInAttributeKey.backgroundColor, - (value) => value != null, + (value) { + return value != null && value != '0x00000000'; // transparent color; + }, ), handler: (editorState, context) => formatHighlight( editorState, diff --git a/frontend/app_flowy/packages/flowy_infra/lib/image.dart b/frontend/app_flowy/packages/flowy_infra/lib/image.dart index e70c8b4bff..21ef1a2970 100644 --- a/frontend/app_flowy/packages/flowy_infra/lib/image.dart +++ b/frontend/app_flowy/packages/flowy_infra/lib/image.dart @@ -1,15 +1,26 @@ import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; -Widget svgWidget(String name, {Color? color}) { - final Widget svg = SvgPicture.asset('assets/images/$name.svg', color: color); - - return svg; -} - Widget svgWithSize(String name, Size size) { return SizedBox.fromSize( size: size, child: svgWidget(name), ); } + +Widget svgWidget(String name, {Size? size, Color? color}) { + if (size != null) { + return SizedBox.fromSize( + size: size, + child: _svgWidget(name, color: color), + ); + } else { + return _svgWidget(name, color: color); + } +} + +Widget _svgWidget(String name, {Color? color}) { + final Widget svg = SvgPicture.asset('assets/images/$name.svg', color: color); + + return svg; +}