diff --git a/packages/notus/lib/src/document/attributes.dart b/packages/notus/lib/src/document/attributes.dart index f2f222075..36532cd87 100644 --- a/packages/notus/lib/src/document/attributes.dart +++ b/packages/notus/lib/src/document/attributes.dart @@ -67,6 +67,7 @@ abstract class NotusAttributeBuilder implements NotusAttributeKey { /// /// * [NotusAttribute.bold] /// * [NotusAttribute.italic] +/// * [NotusAttribute.strikethrough] /// * [NotusAttribute.link] /// * [NotusAttribute.heading] /// * [NotusAttribute.block] @@ -74,10 +75,12 @@ class NotusAttribute implements NotusAttributeBuilder { static final Map _registry = { NotusAttribute.bold.key: NotusAttribute.bold, NotusAttribute.italic.key: NotusAttribute.italic, + NotusAttribute.strikethrough.key: NotusAttribute.strikethrough, NotusAttribute.link.key: NotusAttribute.link, NotusAttribute.heading.key: NotusAttribute.heading, NotusAttribute.block.key: NotusAttribute.block, NotusAttribute.embed.key: NotusAttribute.embed, + NotusAttribute.color.key: NotusAttribute.color, }; // Inline attributes @@ -88,10 +91,46 @@ class NotusAttribute implements NotusAttributeBuilder { /// Italic style attribute. static const italic = _ItalicAttribute(); + /// Italic style attribute. + static const strikethrough = _StrikeThroughAttribute(); + /// Link style attribute. // ignore: const_eval_throws_exception static const link = LinkAttributeBuilder._(); + //color style attribute + static const color = ColorAttributeBuilder._(); + + /// Aliases for [NotusAttribute.color.]. + static NotusAttribute get cPink => color.pink; + static NotusAttribute get cNeonPink => color.neonPink; + static NotusAttribute get cMaroonRed => color.maroonRed; + static NotusAttribute get cCherryRed => color.cherryRed; + static NotusAttribute get cCoralRed => color.coralRed; + static NotusAttribute get cMahogany => color.mahogany; + + static NotusAttribute get cOrange => color.orange; + + static NotusAttribute get cYellow => color.yellow; + static NotusAttribute get cNeonYellow => color.neonYellow; + + static NotusAttribute get cForestGreen => color.forestGreen; + static NotusAttribute get cAppleGreen => color.appleGreen; + static NotusAttribute get cTeaGreen => color.teaGreen; + static NotusAttribute get cNeonGreen => color.neonGreen; + static NotusAttribute get cTealGreen => color.tealGreen; + + static NotusAttribute get cLBlue => color.lightBlue; + static NotusAttribute get cOceanBlue => color.oceanBlue; + static NotusAttribute get cLilBlue => color.lilBlue; + static NotusAttribute get cNavyBlue => color.navyBlue; + + static NotusAttribute get cPlum => color.plum; + static NotusAttribute get cNeonPurple => color.neonPurple; + static NotusAttribute get cSuedePurple => color.suedePurple; + static NotusAttribute get cOrchidPurple => color.orchidPurple; + + // Line attributes /// Heading style attribute. @@ -332,6 +371,11 @@ class _ItalicAttribute extends NotusAttribute { const _ItalicAttribute() : super._('i', NotusAttributeScope.inline, true); } +/// Applies strikethrough style to a text segment. +class _StrikeThroughAttribute extends NotusAttribute { + const _StrikeThroughAttribute() : super._('st', NotusAttributeScope.inline, true); +} + /// Builder for link attribute values. /// /// There is no need to use this class directly, consider using @@ -364,6 +408,43 @@ class HeadingAttributeBuilder extends NotusAttributeBuilder { NotusAttribute get level3 => NotusAttribute._(key, scope, 3); } +/// Builder for color attribute styles. + +class ColorAttributeBuilder extends NotusAttributeBuilder { + static const _kColor = 'color'; + const ColorAttributeBuilder._() + : super._(_kColor, NotusAttributeScope.inline); + + NotusAttribute get pink => NotusAttribute._(key, scope, "ffbcbc"); + NotusAttribute get neonPink => NotusAttribute._(key, scope, "ff3796"); + NotusAttribute get maroonRed => NotusAttribute._(key, scope, "751011"); + NotusAttribute get cherryRed => NotusAttribute._(key, scope, "e43f5a"); + NotusAttribute get coralRed => NotusAttribute._(key, scope, "f47c7c"); + NotusAttribute get mahogany => NotusAttribute._(key, scope, "B64003"); + + NotusAttribute get orange => NotusAttribute._(key, scope, "FE8C03"); + + NotusAttribute get yellow => NotusAttribute._(key, scope, "f7f48b"); + NotusAttribute get neonYellow => NotusAttribute._(key, scope, "fdff38"); + + NotusAttribute get forestGreen => NotusAttribute._(key, scope, "004a18"); + NotusAttribute get appleGreen => NotusAttribute._(key, scope, "a1de93"); + NotusAttribute get teaGreen => NotusAttribute._(key, scope, "acecd5"); + NotusAttribute get neonGreen => NotusAttribute._(key, scope, "00faac"); + NotusAttribute get tealGreen => NotusAttribute._(key, scope, "048481"); + + NotusAttribute get lightBlue => NotusAttribute._(key, scope, "beebe9"); + NotusAttribute get oceanBlue => NotusAttribute._(key, scope, "2ECFFF"); + NotusAttribute get lilBlue => NotusAttribute._(key, scope, "70a1d7"); + NotusAttribute get navyBlue => NotusAttribute._(key, scope, "162447"); + + NotusAttribute get plum => NotusAttribute._(key, scope, "d7aefc"); + NotusAttribute get neonPurple => NotusAttribute._(key, scope, "dc2ade"); + NotusAttribute get suedePurple => NotusAttribute._(key, scope, "834c69"); + NotusAttribute get orchidPurple => NotusAttribute._(key, scope, "543864"); + +} + /// Builder for block attribute styles (number/bullet lists, code and quote). /// /// There is no need to use this class directly, consider using diff --git a/packages/zefyr/example/lib/main.dart b/packages/zefyr/example/lib/main.dart index 833879fc9..875013c00 100644 --- a/packages/zefyr/example/lib/main.dart +++ b/packages/zefyr/example/lib/main.dart @@ -6,8 +6,8 @@ import 'package:flutter/services.dart'; import 'src/form.dart'; import 'src/full_page.dart'; -import 'src/view.dart'; import 'src/text_field_page.dart'; +import 'src/view.dart'; void main() { runApp(ZefyrApp()); @@ -35,10 +35,10 @@ class ZefyrApp extends StatelessWidget { title: 'Zefyr Editor', home: HomePage(), routes: { - "/fullPage": buildFullPage, - "/form": buildFormPage, - "/view": buildViewPage, - "/textinput": buildTextFieldPage, + '/fullPage': buildFullPage, + '/form': buildFormPage, + '/view': buildViewPage, + '/textinput': buildTextFieldPage, }, ); } diff --git a/packages/zefyr/example/lib/quick_start.dart b/packages/zefyr/example/lib/quick_start.dart index bd01e90b8..04ddae498 100644 --- a/packages/zefyr/example/lib/quick_start.dart +++ b/packages/zefyr/example/lib/quick_start.dart @@ -16,7 +16,7 @@ class QuickStartApp extends StatelessWidget { title: 'Quick Start', home: HomePage(), routes: { - "/editor": (context) => EditorPage(), + '/editor': (context) => EditorPage(), }, ); } @@ -27,11 +27,11 @@ class HomePage extends StatelessWidget { Widget build(BuildContext context) { final navigator = Navigator.of(context); return Scaffold( - appBar: AppBar(title: Text("Quick Start")), + appBar: AppBar(title: Text('Quick Start')), body: Center( child: FlatButton( - child: Text("Open editor"), - onPressed: () => navigator.pushNamed("/editor"), + child: Text('Open editor'), + onPressed: () => navigator.pushNamed('/editor'), ), ), ); diff --git a/packages/zefyr/example/lib/src/editor_page.dart b/packages/zefyr/example/lib/src/editor_page.dart index 549dbb71f..66302e280 100644 --- a/packages/zefyr/example/lib/src/editor_page.dart +++ b/packages/zefyr/example/lib/src/editor_page.dart @@ -30,7 +30,7 @@ class EditorPageState extends State { @override Widget build(BuildContext context) { - final Widget body = (_controller == null) + final body = (_controller == null) ? Center(child: CircularProgressIndicator()) : ZefyrScaffold( child: ZefyrEditor( @@ -42,7 +42,7 @@ class EditorPageState extends State { return Scaffold( appBar: AppBar( - title: Text("Editor page"), + title: Text('Editor page'), actions: [ Builder( builder: (context) => IconButton( @@ -59,14 +59,14 @@ class EditorPageState extends State { /// Loads the document asynchronously from a file if it exists, otherwise /// returns default document. Future _loadDocument() async { - final file = File(Directory.systemTemp.path + "/quick_start.json"); + final file = File(Directory.systemTemp.path + '/quick_start.json'); if (await file.exists()) { final contents = await file .readAsString() .then((data) => Future.delayed(Duration(seconds: 1), () => data)); return NotusDocument.fromJson(jsonDecode(contents)); } - final Delta delta = Delta()..insert("Zefyr Quick Start\n"); + final delta = Delta()..insert('Zefyr Quick Start\n'); return NotusDocument.fromDelta(delta); } @@ -75,10 +75,10 @@ class EditorPageState extends State { // `jsonEncode` directly: final contents = jsonEncode(_controller.document); // For this example we save our document to a temporary file. - final file = File(Directory.systemTemp.path + "/quick_start.json"); + final file = File(Directory.systemTemp.path + '/quick_start.json'); // And show a snack bar on success. file.writeAsString(contents).then((_) { - Scaffold.of(context).showSnackBar(SnackBar(content: Text("Saved."))); + Scaffold.of(context).showSnackBar(SnackBar(content: Text('Saved.'))); }); } } diff --git a/packages/zefyr/example/lib/src/form.dart b/packages/zefyr/example/lib/src/form.dart index 1b7024773..829ec399c 100644 --- a/packages/zefyr/example/lib/src/form.dart +++ b/packages/zefyr/example/lib/src/form.dart @@ -27,7 +27,10 @@ class _FormEmbeddedScreenState extends State { children: [ TextField(decoration: InputDecoration(labelText: 'Name')), buildEditor(), - TextField(decoration: InputDecoration(labelText: 'Email')), + TextField( + decoration: InputDecoration(labelText: 'Details'), + maxLines: 3, + ), ], ); @@ -81,7 +84,7 @@ class _FormEmbeddedScreenState extends State { return [ CheckedPopupMenuItem( value: _Options.darkTheme, - child: Text("Dark theme"), + child: Text('Dark theme'), checked: _darkTheme, ), ]; diff --git a/packages/zefyr/example/lib/src/full_page.dart b/packages/zefyr/example/lib/src/full_page.dart index 599f50f7e..d3f821ebf 100644 --- a/packages/zefyr/example/lib/src/full_page.dart +++ b/packages/zefyr/example/lib/src/full_page.dart @@ -111,7 +111,7 @@ class _FullPageEditorScreenState extends State { return [ CheckedPopupMenuItem( value: _Options.darkTheme, - child: Text("Dark theme"), + child: Text('Dark theme'), checked: _darkTheme, ), ]; diff --git a/packages/zefyr/example/lib/src/images.dart b/packages/zefyr/example/lib/src/images.dart index 167e68d7b..cc00d5d16 100644 --- a/packages/zefyr/example/lib/src/images.dart +++ b/packages/zefyr/example/lib/src/images.dart @@ -19,9 +19,10 @@ class CustomImageDelegate implements ZefyrImageDelegate { @override Future pickImage(ImageSource source) async { - final file = await ImagePicker.pickImage(source: source); + final picker = ImagePicker(); + final file = await picker.getImage(source: source); if (file == null) return null; - return file.uri.toString(); + return file.path; } @override diff --git a/packages/zefyr/example/lib/src/text_field_page.dart b/packages/zefyr/example/lib/src/text_field_page.dart index e60c3eec7..61e561422 100644 --- a/packages/zefyr/example/lib/src/text_field_page.dart +++ b/packages/zefyr/example/lib/src/text_field_page.dart @@ -37,7 +37,7 @@ class _TextFieldScreenState extends State { padding: const EdgeInsets.all(8.0), child: TextField( controller: _singleTextFieldcontroller, - maxLines: 1000, + maxLines: 10, ), ), ], diff --git a/packages/zefyr/example/macos/Podfile.lock b/packages/zefyr/example/macos/Podfile.lock index 8fdec5c6f..b01eb79f3 100644 --- a/packages/zefyr/example/macos/Podfile.lock +++ b/packages/zefyr/example/macos/Podfile.lock @@ -24,4 +24,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: d8ba9b3e9e93c62c74a660b46c6fcb09f03991a7 -COCOAPODS: 1.8.4 +COCOAPODS: 1.9.3 diff --git a/packages/zefyr/example/macos/Runner.xcodeproj/project.pbxproj b/packages/zefyr/example/macos/Runner.xcodeproj/project.pbxproj index 479743c78..e27cf6cd0 100644 --- a/packages/zefyr/example/macos/Runner.xcodeproj/project.pbxproj +++ b/packages/zefyr/example/macos/Runner.xcodeproj/project.pbxproj @@ -21,6 +21,7 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 304B2F9BA7EA031BCC7A345B /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BF92DD763823A4EA8AB75163 /* Pods_Runner.framework */; }; 335BBD1B22A9A15E00E9071D /* GeneratedPluginRegistrant.swift in Sources */ = {isa = PBXBuildFile; fileRef = 335BBD1A22A9A15E00E9071D /* GeneratedPluginRegistrant.swift */; }; 33CC10F12044A3C60003C045 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33CC10F02044A3C60003C045 /* AppDelegate.swift */; }; 33CC10F32044A3C60003C045 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 33CC10F22044A3C60003C045 /* Assets.xcassets */; }; @@ -30,7 +31,6 @@ 33D1A10522148B93006C7A3E /* FlutterMacOS.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = 33D1A10322148B71006C7A3E /* FlutterMacOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; D73912F022F37F9E000D13A0 /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; }; D73912F222F3801D000D13A0 /* App.framework in Bundle Framework */ = {isa = PBXBuildFile; fileRef = D73912EF22F37F9E000D13A0 /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - D9B52C3D80BE5A7C2CF8AE52 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 46B9CD1CE70311075A71806A /* Pods_Runner.framework */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -74,12 +74,12 @@ 33E51913231747F40026EE4D /* DebugProfile.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = DebugProfile.entitlements; sourceTree = ""; }; 33E51914231749380026EE4D /* Release.entitlements */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.entitlements; path = Release.entitlements; sourceTree = ""; }; 33E5194F232828860026EE4D /* AppInfo.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = AppInfo.xcconfig; sourceTree = ""; }; - 3CAC29814F056DDA0FFDA321 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; - 46B9CD1CE70311075A71806A /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; - 7231E59B042100FE70779FA7 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; + 46BBF557A38EB3C716FE3531 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = ""; }; 7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = Release.xcconfig; sourceTree = ""; }; + 852026E2558F66F9CF11987C /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = ""; }; 9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; path = Debug.xcconfig; sourceTree = ""; }; - A15C1F8D36F3ABFECC3331FA /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + B4EBA9765EA9857FF9109C20 /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = ""; }; + BF92DD763823A4EA8AB75163 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D73912EF22F37F9E000D13A0 /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/ephemeral/App.framework; sourceTree = SOURCE_ROOT; }; /* End PBXFileReference section */ @@ -90,13 +90,24 @@ files = ( D73912F022F37F9E000D13A0 /* App.framework in Frameworks */, 33D1A10422148B71006C7A3E /* FlutterMacOS.framework in Frameworks */, - D9B52C3D80BE5A7C2CF8AE52 /* Pods_Runner.framework in Frameworks */, + 304B2F9BA7EA031BCC7A345B /* Pods_Runner.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ + 2CBFAE841A79D31B1DCACCA9 /* Pods */ = { + isa = PBXGroup; + children = ( + 852026E2558F66F9CF11987C /* Pods-Runner.debug.xcconfig */, + 46BBF557A38EB3C716FE3531 /* Pods-Runner.release.xcconfig */, + B4EBA9765EA9857FF9109C20 /* Pods-Runner.profile.xcconfig */, + ); + name = Pods; + path = Pods; + sourceTree = ""; + }; 33BA886A226E78AF003329D5 /* Configs */ = { isa = PBXGroup; children = ( @@ -115,7 +126,7 @@ 33CEB47122A05771004F2AC0 /* Flutter */, 33CC10EE2044A3C60003C045 /* Products */, D73912EC22F37F3D000D13A0 /* Frameworks */, - ED4C00A410968954382A9141 /* Pods */, + 2CBFAE841A79D31B1DCACCA9 /* Pods */, ); sourceTree = ""; }; @@ -167,22 +178,11 @@ D73912EC22F37F3D000D13A0 /* Frameworks */ = { isa = PBXGroup; children = ( - 46B9CD1CE70311075A71806A /* Pods_Runner.framework */, + BF92DD763823A4EA8AB75163 /* Pods_Runner.framework */, ); name = Frameworks; sourceTree = ""; }; - ED4C00A410968954382A9141 /* Pods */ = { - isa = PBXGroup; - children = ( - 7231E59B042100FE70779FA7 /* Pods-Runner.debug.xcconfig */, - 3CAC29814F056DDA0FFDA321 /* Pods-Runner.release.xcconfig */, - A15C1F8D36F3ABFECC3331FA /* Pods-Runner.profile.xcconfig */, - ); - name = Pods; - path = Pods; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -190,13 +190,13 @@ isa = PBXNativeTarget; buildConfigurationList = 33CC10FB2044A3C60003C045 /* Build configuration list for PBXNativeTarget "Runner" */; buildPhases = ( - 7249C776D62A8EAB6DFDBF58 /* [CP] Check Pods Manifest.lock */, + 1F60D938195A1FEE2BCD4AB3 /* [CP] Check Pods Manifest.lock */, 33CC10E92044A3C60003C045 /* Sources */, 33CC10EA2044A3C60003C045 /* Frameworks */, 33CC10EB2044A3C60003C045 /* Resources */, 33CC110E2044A8840003C045 /* Bundle Framework */, 3399D490228B24CF009A79C7 /* ShellScript */, - 59DDC0AE6A116FE294C2076E /* [CP] Embed Pods Frameworks */, + 34A999EBD12E4B258DDB9ECE /* [CP] Embed Pods Frameworks */, ); buildRules = ( ); @@ -266,7 +266,7 @@ /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3399D490228B24CF009A79C7 /* ShellScript */ = { + 1F60D938195A1FEE2BCD4AB3 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -274,70 +274,70 @@ inputFileListPaths = ( ); inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( ); outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + showEnvVarsInLog = 0; }; - 33CC111E2044C6BF0003C045 /* ShellScript */ = { + 3399D490228B24CF009A79C7 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - Flutter/ephemeral/FlutterInputs.xcfilelist, ); inputPaths = ( - Flutter/ephemeral/tripwire, ); outputFileListPaths = ( - Flutter/ephemeral/FlutterOutputs.xcfilelist, ); outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh\ntouch Flutter/ephemeral/tripwire\n"; + shellScript = "echo \"$PRODUCT_NAME.app\" > \"$PROJECT_DIR\"/Flutter/ephemeral/.app_filename\n"; }; - 59DDC0AE6A116FE294C2076E /* [CP] Embed Pods Frameworks */ = { + 33CC111E2044C6BF0003C045 /* ShellScript */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + Flutter/ephemeral/FlutterInputs.xcfilelist, + ); + inputPaths = ( + Flutter/ephemeral/tripwire, ); - name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( + Flutter/ephemeral/FlutterOutputs.xcfilelist, + ); + outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; - showEnvVarsInLog = 0; + shellScript = "\"$FLUTTER_ROOT\"/packages/flutter_tools/bin/macos_assemble.sh && touch Flutter/ephemeral/tripwire"; }; - 7249C776D62A8EAB6DFDBF58 /* [CP] Check Pods Manifest.lock */ = { + 34A999EBD12E4B258DDB9ECE /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Embed Pods Frameworks"; outputFileListPaths = ( ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt", - ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/packages/zefyr/lib/src/widgets/buttons.dart b/packages/zefyr/lib/src/widgets/buttons.dart index f6378c1e4..170645848 100644 --- a/packages/zefyr/lib/src/widgets/buttons.dart +++ b/packages/zefyr/lib/src/widgets/buttons.dart @@ -12,8 +12,8 @@ import 'toolbar.dart'; /// A button used in [ZefyrToolbar]. /// -/// Create an instance of this widget with [ZefyrButton.icon] or -/// [ZefyrButton.text] constructors. +/// Create an instance of this widget with [ZefyrButton.icon], +/// [ZefyrButton.text], or [ZefyrButton.widget] constructors. /// /// Toolbar buttons are normally created by a [ZefyrToolbarDelegate]. class ZefyrButton extends StatelessWidget { @@ -25,12 +25,30 @@ class ZefyrButton extends StatelessWidget { this.onPressed, }) : assert(action != null), assert(icon != null), + _circleWidget = null, _icon = icon, _iconSize = iconSize, _text = null, _textStyle = null, super(); + //create toolbar button with widget, size 20 + ZefyrButton.widget({ + @required this.action, + @required Widget circle, + double iconSize, + this.onPressed, + }) : assert(action != null), + assert(circle != null), + _icon = null, + _circleWidget = circle, + _iconSize = iconSize, + _text = null, + _textStyle = null, + super(); + + + /// Creates a toolbar button containing text. /// /// Note that [ZefyrButton] has fixed width and does not expand to accommodate @@ -43,6 +61,7 @@ class ZefyrButton extends StatelessWidget { }) : assert(action != null), assert(text != null), _icon = null, + _circleWidget = null, _iconSize = null, _text = text, _textStyle = style, @@ -53,6 +72,7 @@ class ZefyrButton extends StatelessWidget { final IconData _icon; final double _iconSize; final String _text; + final Container _circleWidget; final TextStyle _textStyle; /// Callback to trigger when this button is tapped. @@ -80,8 +100,7 @@ class ZefyrButton extends StatelessWidget { color: _getColor(editor, toolbarTheme), onPressed: _getPressedHandler(editor, toolbar), ); - } else { - assert(_text != null); + } else if (_text != null){ var style = _textStyle ?? TextStyle(); style = style.copyWith(color: iconColor); return RawZefyrButton( @@ -90,6 +109,15 @@ class ZefyrButton extends StatelessWidget { color: _getColor(editor, toolbarTheme), onPressed: _getPressedHandler(editor, toolbar), ); + }else{ + assert(_circleWidget != null); + return RawZefyrButton( + action: action, + child: _circleWidget, + color: _getColor(editor, toolbarTheme), + onPressed: _getPressedHandler(editor, toolbar), + ); + } } @@ -235,6 +263,110 @@ class _HeadingButtonState extends State { } } +// Controls color styles. +/// +/// When pressed, this button displays overlay toolbar with +/// buttons for each color. +class ColorButton extends StatefulWidget { + const ColorButton({Key key}) : super(key: key); + + @override + _ColorButtonState createState() => _ColorButtonState(); +} + +class _ColorButtonState extends State { + @override + Widget build(BuildContext context) { + final toolbar = ZefyrToolbar.of(context); + return toolbar.buildButton( + context, + ZefyrToolbarAction.color, + onPressed: showOverlay, + ); + } + + void showOverlay() { + final toolbar = ZefyrToolbar.of(context); + toolbar.showOverlay(buildOverlay); + } + + Widget buildOverlay(BuildContext context) { + final toolbar = ZefyrToolbar.of(context); + final buttons = Row( + children: [ + SizedBox(width: 8.0), + ModeColorButton(1), + ModeColorButton(0), + ], + ); + return ZefyrToolbarScaffold(body: buttons); + } +} + +//Light mode and dark mode colors +// +//Shows colors for light mode and dark mode depending on what is passed in: +//0 - Dark Mode; 1 - Light Mode +class ModeColorButton extends StatefulWidget { + final int modeChosen; + ModeColorButton(this.modeChosen); + @override + _ModeColorButtonState createState() => _ModeColorButtonState(); +} + +class _ModeColorButtonState extends State { + + @override + Widget build(BuildContext context) { + final toolbar = ZefyrToolbar.of(context); + return toolbar.buildButton( + context, + (widget.modeChosen == 1) ? ZefyrToolbarAction.lightMode : ZefyrToolbarAction.darkMode, + onPressed: showOverlay, + ); + } + + void showOverlay() { + final toolbar = ZefyrToolbar.of(context); + toolbar.showOverlay(buildOverlay); + } + + Widget buildOverlay(BuildContext context) { + final toolbar = ZefyrToolbar.of(context); + List darkModeColors = [ + SizedBox(width: 8.0), + toolbar.buildButton(context, ZefyrToolbarAction.colorPink), + toolbar.buildButton(context, ZefyrToolbarAction.colorNeonPink), + toolbar.buildButton(context, ZefyrToolbarAction.colorCherryRed), + toolbar.buildButton(context, ZefyrToolbarAction.colorCoralRed), + toolbar.buildButton(context, ZefyrToolbarAction.colorOrange), + toolbar.buildButton(context, ZefyrToolbarAction.colorYellow), + toolbar.buildButton(context, ZefyrToolbarAction.colorNeonYellow), + toolbar.buildButton(context, ZefyrToolbarAction.colorAppleGreen), + toolbar.buildButton(context, ZefyrToolbarAction.colorTeaGreen), + toolbar.buildButton(context, ZefyrToolbarAction.colorNeonGreen), + toolbar.buildButton(context, ZefyrToolbarAction.colorLightBlue), + toolbar.buildButton(context, ZefyrToolbarAction.colorOceanBlue), + toolbar.buildButton(context, ZefyrToolbarAction.colorLilBlue), + toolbar.buildButton(context, ZefyrToolbarAction.colorPlum), + toolbar.buildButton(context, ZefyrToolbarAction.colorNeonPurple), + ]; + + List lightModeColors = [ + SizedBox(width: 8.0), + toolbar.buildButton(context, ZefyrToolbarAction.colorMaroonRed), + toolbar.buildButton(context, ZefyrToolbarAction.colorCherryRed), + toolbar.buildButton(context, ZefyrToolbarAction.colorMahogany), + toolbar.buildButton(context, ZefyrToolbarAction.colorForestGreen), + toolbar.buildButton(context, ZefyrToolbarAction.colorTealGreen), + toolbar.buildButton(context, ZefyrToolbarAction.colorNavyBlue), + toolbar.buildButton(context, ZefyrToolbarAction.colorSuedePurple), + toolbar.buildButton(context, ZefyrToolbarAction.colorOrchidPurple), + ]; + return ZefyrToolbarScaffold(body: ZefyrButtonList(buttons: (widget.modeChosen == 1) ? lightModeColors : darkModeColors,)); + } +} + /// Controls image attribute. /// /// When pressed, this button displays overlay toolbar with three diff --git a/packages/zefyr/lib/src/widgets/common.dart b/packages/zefyr/lib/src/widgets/common.dart index 2e5cbc4f9..0a07ce1f2 100644 --- a/packages/zefyr/lib/src/widgets/common.dart +++ b/packages/zefyr/lib/src/widgets/common.dart @@ -138,16 +138,122 @@ class _ZefyrLineState extends State { } TextStyle _getTextStyle(NotusStyle style, ZefyrThemeData theme) { - var result = TextStyle(); + TextStyle result = TextStyle(); + final hexStringToColor = (String hex) { + hex = hex.replaceFirst('#', ''); + hex = hex.length == 6 ? 'ff' + hex : hex; + int val = int.parse(hex, radix: 16); + return Color(val); + }; + + if (style.containsSame(NotusAttribute.bold)) { result = result.merge(theme.attributeTheme.bold); } if (style.containsSame(NotusAttribute.italic)) { result = result.merge(theme.attributeTheme.italic); } + if (style.containsSame(NotusAttribute.strikethrough)) { + result = result.merge(theme.attributeTheme.strikethrough); + } if (style.contains(NotusAttribute.link)) { result = result.merge(theme.attributeTheme.link); } + + //Colors + if (style.contains(NotusAttribute.cPink)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cPink)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cNeonPink)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cNeonPink)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cMaroonRed)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cMaroonRed)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cCherryRed)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cCherryRed)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cCoralRed)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cCoralRed)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cMahogany)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cMahogany)); + result = result.copyWith(color: textColor); + } + + if (style.contains(NotusAttribute.cOrange)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cOrange)); + result = result.copyWith(color: textColor); + } + + if (style.contains(NotusAttribute.cYellow)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cYellow)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cNeonYellow)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cNeonYellow)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cForestGreen)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cForestGreen)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cAppleGreen)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cAppleGreen)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cTeaGreen)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cTeaGreen)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cNeonGreen)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cNeonGreen)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cTealGreen)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cTealGreen)); + result = result.copyWith(color: textColor); + } + + if (style.contains(NotusAttribute.cLBlue)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cLBlue)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cOceanBlue)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cOceanBlue)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cLilBlue)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cLilBlue)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cNavyBlue)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cNavyBlue)); + result = result.copyWith(color: textColor); + } + + if (style.contains(NotusAttribute.cPlum)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cPlum)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cNeonPurple)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cNeonPurple)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cSuedePurple)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cSuedePurple)); + result = result.copyWith(color: textColor); + } + if (style.contains(NotusAttribute.cOrchidPurple)) { + final textColor = hexStringToColor(style.value(NotusAttribute.cOrchidPurple)); + result = result.copyWith(color: textColor); + } + } return result; } diff --git a/packages/zefyr/lib/src/widgets/controller.dart b/packages/zefyr/lib/src/widgets/controller.dart index 1117ab617..0c5e2853d 100644 --- a/packages/zefyr/lib/src/widgets/controller.dart +++ b/packages/zefyr/lib/src/widgets/controller.dart @@ -29,7 +29,7 @@ enum FocusOwner { class ZefyrController extends ChangeNotifier { ZefyrController(NotusDocument document) : assert(document != null), - document = document; + document = document; /// Zefyr document managed by this controller. final NotusDocument document; @@ -167,7 +167,7 @@ class ZefyrController extends ChangeNotifier { if (length == 0 && (attribute.key == NotusAttribute.bold.key || - attribute.key == NotusAttribute.italic.key)) { + attribute.key == NotusAttribute.italic.key|| attribute.key == NotusAttribute.strikethrough.key|| attribute.key == NotusAttribute.color.key)) { // Add the attribute to our toggledStyle. It will be used later upon insertion. _toggledStyles = toggledStyles.put(attribute); } @@ -210,7 +210,7 @@ class ZefyrController extends ChangeNotifier { return TextEditingValue( text: document.toPlainText(), selection: selection, - composing: TextRange.collapsed(0), + composing: TextRange.collapsed(-1), ); } diff --git a/packages/zefyr/lib/src/widgets/editable_text.dart b/packages/zefyr/lib/src/widgets/editable_text.dart index ce5176ad2..280d06e61 100644 --- a/packages/zefyr/lib/src/widgets/editable_text.dart +++ b/packages/zefyr/lib/src/widgets/editable_text.dart @@ -3,6 +3,7 @@ // BSD-style license that can be found in the LICENSE file. import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter/widgets.dart'; import 'package:notus/notus.dart'; @@ -163,7 +164,10 @@ class _ZefyrEditableTextState extends State controls: widget.selectionControls ?? defaultSelectionControls(context), )); - return Stack(fit: StackFit.expand, children: layers); + return MouseRegion( + cursor: SystemMouseCursors.text, + child: Stack(fit: StackFit.expand, children: layers), + ); } @override diff --git a/packages/zefyr/lib/src/widgets/input.dart b/packages/zefyr/lib/src/widgets/input.dart index 49954ce9e..e569d2056 100644 --- a/packages/zefyr/lib/src/widgets/input.dart +++ b/packages/zefyr/lib/src/widgets/input.dart @@ -46,10 +46,13 @@ class InputConnectionController implements TextInputClient { keyboardAppearance: keyboardAppearance, textCapitalization: TextCapitalization.sentences, ), - )..setEditingState(value); + ) + ..show() + ..setEditingState(value); _sentRemoteValues.add(value); + } else { + _textInputConnection.show(); } - _textInputConnection.show(); } /// Closes input connection if it's currently open. Otherwise does nothing. @@ -193,4 +196,9 @@ class InputConnectionController implements TextInputClient { void showAutocorrectionPromptRect(int start, int end) { // TODO: implement showAutocorrectionPromptRect } + + @override + void performPrivateCommand(String action, Map data) { + // TODO: implement performPrivateCommand + } } diff --git a/packages/zefyr/lib/src/widgets/theme.dart b/packages/zefyr/lib/src/widgets/theme.dart index 70b063fbc..1b859b34f 100644 --- a/packages/zefyr/lib/src/widgets/theme.dart +++ b/packages/zefyr/lib/src/widgets/theme.dart @@ -287,6 +287,9 @@ class AttributeTheme { /// Style used to render "italic" text. final TextStyle italic; + /// Style used to render "strikethrough" text. + final TextStyle strikethrough; + /// Style used to render text containing links. final TextStyle link; @@ -315,6 +318,7 @@ class AttributeTheme { AttributeTheme({ this.bold, this.italic, + this.strikethrough, this.link, this.heading1, this.heading2, @@ -347,6 +351,7 @@ class AttributeTheme { return AttributeTheme( bold: TextStyle(fontWeight: FontWeight.bold), italic: TextStyle(fontStyle: FontStyle.italic), + strikethrough: TextStyle(decoration: TextDecoration.lineThrough), link: TextStyle( decoration: TextDecoration.underline, color: theme.accentColor, @@ -412,6 +417,7 @@ class AttributeTheme { AttributeTheme copyWith({ TextStyle bold, TextStyle italic, + TextStyle strikethrough, TextStyle link, LineTheme heading1, LineTheme heading2, @@ -424,6 +430,7 @@ class AttributeTheme { return AttributeTheme( bold: bold ?? this.bold, italic: italic ?? this.italic, + strikethrough: strikethrough ?? this.strikethrough, link: link ?? this.link, heading1: heading1 ?? this.heading1, heading2: heading2 ?? this.heading2, @@ -442,6 +449,7 @@ class AttributeTheme { return copyWith( bold: bold?.merge(other.bold) ?? other.bold, italic: italic?.merge(other.italic) ?? other.italic, + strikethrough: strikethrough?.merge(other.strikethrough) ?? other.strikethrough, link: link?.merge(other.link) ?? other.link, heading1: heading1?.merge(other.heading1) ?? other.heading1, heading2: heading2?.merge(other.heading2) ?? other.heading2, @@ -459,6 +467,7 @@ class AttributeTheme { final AttributeTheme otherTheme = other; return (otherTheme.bold == bold) && (otherTheme.italic == italic) && + (otherTheme.strikethrough == strikethrough) && (otherTheme.link == link) && (otherTheme.heading1 == heading1) && (otherTheme.heading2 == heading2) && @@ -474,6 +483,7 @@ class AttributeTheme { return hashList([ bold, italic, + strikethrough, link, heading1, heading2, diff --git a/packages/zefyr/lib/src/widgets/toolbar.dart b/packages/zefyr/lib/src/widgets/toolbar.dart index a5a1e33e4..49a95ccac 100644 --- a/packages/zefyr/lib/src/widgets/toolbar.dart +++ b/packages/zefyr/lib/src/widgets/toolbar.dart @@ -15,6 +15,7 @@ import 'theme.dart'; enum ZefyrToolbarAction { bold, italic, + strikethrough, link, unlink, clipboardCopy, @@ -27,18 +28,46 @@ enum ZefyrToolbarAction { numberList, code, quote, - horizontalRule, image, cameraImage, galleryImage, hideKeyboard, close, confirm, + + + color, + lightMode, + darkMode, + + colorPink, + colorNeonPink, + colorMaroonRed, + colorCherryRed, + colorCoralRed, + colorMahogany, + colorOrange, + colorYellow, + colorNeonYellow, + colorForestGreen, + colorAppleGreen, + colorTeaGreen, + colorNeonGreen, + colorTealGreen, + colorLightBlue, + colorOceanBlue, + colorLilBlue, + colorNavyBlue, + colorPlum, + colorNeonPurple, + colorSuedePurple, + colorOrchidPurple } final kZefyrToolbarAttributeActions = { ZefyrToolbarAction.bold: NotusAttribute.bold, ZefyrToolbarAction.italic: NotusAttribute.italic, + ZefyrToolbarAction.strikethrough: NotusAttribute.strikethrough, ZefyrToolbarAction.link: NotusAttribute.link, ZefyrToolbarAction.heading: NotusAttribute.heading, ZefyrToolbarAction.headingLevel1: NotusAttribute.heading.level1, @@ -48,7 +77,31 @@ final kZefyrToolbarAttributeActions = { ZefyrToolbarAction.numberList: NotusAttribute.block.numberList, ZefyrToolbarAction.code: NotusAttribute.block.code, ZefyrToolbarAction.quote: NotusAttribute.block.quote, - ZefyrToolbarAction.horizontalRule: NotusAttribute.embed.horizontalRule, + ZefyrToolbarAction.color: NotusAttribute.color, + + ZefyrToolbarAction.colorPink: NotusAttribute.color.pink, + ZefyrToolbarAction.colorNeonPink: NotusAttribute.color.neonPink, + ZefyrToolbarAction.colorMaroonRed: NotusAttribute.color.maroonRed, + ZefyrToolbarAction.colorCherryRed: NotusAttribute.color.cherryRed, + ZefyrToolbarAction.colorCoralRed: NotusAttribute.color.coralRed, + ZefyrToolbarAction.colorMahogany: NotusAttribute.color.mahogany, + ZefyrToolbarAction.colorOrange: NotusAttribute.color.orange, + ZefyrToolbarAction.colorYellow: NotusAttribute.color.yellow, + ZefyrToolbarAction.colorNeonYellow: NotusAttribute.color.neonYellow, + ZefyrToolbarAction.colorForestGreen: NotusAttribute.color.forestGreen, + ZefyrToolbarAction.colorAppleGreen: NotusAttribute.color.appleGreen, + ZefyrToolbarAction.colorTeaGreen: NotusAttribute.color.teaGreen, + ZefyrToolbarAction.colorNeonGreen: NotusAttribute.color.neonGreen, + ZefyrToolbarAction.colorTealGreen: NotusAttribute.color.tealGreen, + ZefyrToolbarAction.colorLightBlue: NotusAttribute.color.lightBlue, + ZefyrToolbarAction.colorOceanBlue: NotusAttribute.color.oceanBlue, + ZefyrToolbarAction.colorLilBlue: NotusAttribute.color.lilBlue, + ZefyrToolbarAction.colorNavyBlue: NotusAttribute.color.navyBlue, + ZefyrToolbarAction.colorPlum: NotusAttribute.color.plum, + ZefyrToolbarAction.colorNeonPurple: NotusAttribute.color.neonPurple, + ZefyrToolbarAction.colorSuedePurple: NotusAttribute.color.suedePurple, + ZefyrToolbarAction.colorOrchidPurple: NotusAttribute.color.orchidPurple, + }; /// Allows customizing appearance of [ZefyrToolbar]. @@ -164,7 +217,7 @@ class ZefyrToolbarState extends State } Future showOverlay(WidgetBuilder builder) async { - assert(_overlayBuilder == null); +// assert(_overlayBuilder == null); final completer = Completer(); setState(() { _overlayBuilder = builder; @@ -250,15 +303,16 @@ class ZefyrToolbarState extends State List _buildButtons(BuildContext context) { final buttons = [ + ColorButton(), buildButton(context, ZefyrToolbarAction.bold), buildButton(context, ZefyrToolbarAction.italic), + buildButton(context, ZefyrToolbarAction.strikethrough), LinkButton(), HeadingButton(), buildButton(context, ZefyrToolbarAction.bulletList), buildButton(context, ZefyrToolbarAction.numberList), buildButton(context, ZefyrToolbarAction.quote), buildButton(context, ZefyrToolbarAction.code), - buildButton(context, ZefyrToolbarAction.horizontalRule), if (editor.imageDelegate != null) ImageButton(), ]; return buttons; @@ -353,6 +407,11 @@ class _DefaultZefyrToolbarDelegate implements ZefyrToolbarDelegate { ZefyrToolbarAction.hideKeyboard: Icons.keyboard_hide, ZefyrToolbarAction.close: Icons.close, ZefyrToolbarAction.confirm: Icons.check, + ZefyrToolbarAction.color: Icons.color_lens, + ZefyrToolbarAction.darkMode: Icons.brightness_2, + ZefyrToolbarAction.lightMode: Icons.brightness_7, + ZefyrToolbarAction.strikethrough: Icons.format_strikethrough, + }; static const kSpecialIconSizes = { @@ -369,6 +428,32 @@ class _DefaultZefyrToolbarDelegate implements ZefyrToolbarDelegate { ZefyrToolbarAction.headingLevel3: 'H3', }; + static const kColorCircles = { + ZefyrToolbarAction.colorPink: Color(0xFFffbcbc), + ZefyrToolbarAction.colorNeonPink: Color(0xFFff3796), + ZefyrToolbarAction.colorMaroonRed: Color(0xFF751011), + ZefyrToolbarAction.colorCherryRed: Color(0xFFe43f5a), + ZefyrToolbarAction.colorCoralRed: Color(0xFFf47c7c), + ZefyrToolbarAction.colorMahogany: Color(0xFFB64003), + ZefyrToolbarAction.colorOrange: Color(0xFFFE8C03), + ZefyrToolbarAction.colorYellow: Color(0xFFf7f48b), + ZefyrToolbarAction.colorNeonYellow: Color(0xFFfdff38), + ZefyrToolbarAction.colorForestGreen: Color(0xFF004a18), + ZefyrToolbarAction.colorAppleGreen: Color(0xFFa1de93), + ZefyrToolbarAction.colorTeaGreen: Color(0xFFacecd5), + ZefyrToolbarAction.colorNeonGreen: Color(0xFF00faac), + ZefyrToolbarAction.colorTealGreen: Color(0xFF048481), + ZefyrToolbarAction.colorLightBlue: Color(0xFFbeebe9), + ZefyrToolbarAction.colorOceanBlue: Color(0xFF2ECFFF), + ZefyrToolbarAction.colorLilBlue: Color(0xFF70a1d7), + ZefyrToolbarAction.colorNavyBlue: Color(0xFF162447), + ZefyrToolbarAction.colorPlum: Color(0xFFd7aefc), + ZefyrToolbarAction.colorNeonPurple: Color(0xFFdc2ade), + ZefyrToolbarAction.colorSuedePurple: Color(0xFF834c69), + ZefyrToolbarAction.colorOrchidPurple: Color(0xFF543864), + + }; + @override Widget buildButton(BuildContext context, ZefyrToolbarAction action, {VoidCallback onPressed}) { @@ -382,7 +467,7 @@ class _DefaultZefyrToolbarDelegate implements ZefyrToolbarDelegate { iconSize: size, onPressed: onPressed, ); - } else { + }else if (kDefaultButtonTexts.containsKey(action)) { final text = kDefaultButtonTexts[action]; assert(text != null); final style = theme.textTheme.caption @@ -393,6 +478,21 @@ class _DefaultZefyrToolbarDelegate implements ZefyrToolbarDelegate { style: style, onPressed: onPressed, ); + }else { + final color = kColorCircles[action]; + assert(color != null); + return ZefyrButton.widget( + action: action, + circle: Container( + width: 20, + height: 20, + decoration: new BoxDecoration( + color: color, + shape: BoxShape.circle, + ) + ), + onPressed: onPressed, + ); } } }