diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml new file mode 100644 index 00000000..f45e642e --- /dev/null +++ b/.github/workflows/dart.yml @@ -0,0 +1,42 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Dart + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + # Note: This workflow uses the latest stable version of the Dart SDK. + # You can specify other versions if desired, see documentation here: + # https://github.com/dart-lang/setup-dart/blob/main/README.md + # - uses: dart-lang/setup-dart@v1 + - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 + + - name: Install dependencies + run: dart pub get + + # Uncomment this step to verify the use of 'dart format' on each commit. + # - name: Verify formatting + # run: dart format --output=none --set-exit-if-changed . + + # Consider passing '--fatal-infos' for slightly stricter analysis. + - name: Analyze project source + run: dart analyze + + # Your project will need to have tests in test/ and a dependency on + # package:test for this step to succeed. Note that Flutter projects will + # want to change this to 'flutter test'. + - name: Run tests + run: dart test diff --git a/.github/workflows/flutter.yml b/.github/workflows/flutter.yml new file mode 100644 index 00000000..97c5382e --- /dev/null +++ b/.github/workflows/flutter.yml @@ -0,0 +1,42 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. + +name: Dart + +on: + push: + branches: [ "master" ] + pull_request: + branches: [ "master" ] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + + # Note: This workflow uses the latest stable version of the Dart SDK. + # You can specify other versions if desired, see documentation here: + # https://github.com/dart-lang/setup-dart/blob/main/README.md + # - uses: dart-lang/setup-dart@v1 + - uses: dart-lang/setup-dart@9a04e6d73cca37bd455e0608d7e5092f881fd603 + + - name: Install dependencies + run: flutter pub get + + # Uncomment this step to verify the use of 'dart format' on each commit. + # - name: Verify formatting + # run: dart format --output=none --set-exit-if-changed . + + # Consider passing '--fatal-infos' for slightly stricter analysis. + - name: Analyze project source + run: flutter analyze + + # Your project will need to have tests in test/ and a dependency on + # package:test for this step to succeed. Note that Flutter projects will + # want to change this to 'flutter test'. + - name: Run tests + run: flutter test diff --git a/CHANGELOG.md b/CHANGELOG.md index a145802f..cc22b2c5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,22 +1,96 @@ -## [2.5.1] = 2023-01-25 +## [3.2.0] = 2023-1-11 + +* changed how the mathMl to Latex works, now faster + +## [3.1.0] = 2023-1-8 + +* changed how the latex to mathMl works, now faster + +## [3.0.0] = 2023-1-4 + +* compatibility + +## [2.6.9+1] = 2023-1-2 + +* improved the math keyboard dialog + +## [2.6.9] = 2023-1-2 + +* improved the math keyboard dialog + +## [2.6.8] = 2023-12-31 + +* moved the math keyboard to the controller + +## [2.6.7] = 2023-12-20 + +* customizable math keyboard + +## [2.6.7] = 2023-12-20 + +* improved performance + +## [2.6.6] = 2023-12-20 + +* Image Upload was turned off, now its on + +## [2.6.5] = 2023-12-20 + +* Version Name + +## [2.6.4] = 2023-12-20 + +* Fixed Cursor bug in math keyboard + +## [2.6.3] = 2023-12-20 + +* Fixed the assets for name change + +## [2.6.2] = 2023-12-20 + +* Dart formatter +* + +## [2.6.1] = 2023-12-20 + +* Update pubspec +* Added repo url + +## [2.6.0] = 2023-12-20 + +* Bug fixes +* Added a Custom Math Keyboard + +## [2.5.2] = 2023-12-20 + +* Added latex +* Added dependencies + +## [2.5.1] = 2023-12-20 + * Fix build issues on Flutter 3.4.0+ due to assets directory * Update dependencies ## [2.5.0] - 2022-06-04 + * Support Flutter 3.0 (remove warnings) (@Cteq3132) -* [BREAKING] Support modifying `foreColorSelected` and `backColorSelected` when using a custom dialog for font coloring - * If you are using a custom `updateStatus` function for the font coloring, that function is now defined as `updateStatus(Color)` +* [BREAKING] Support modifying `foreColorSelected` and `backColorSelected` when using a custom + dialog for font coloring + * If you are using a custom `updateStatus` function for the font coloring, that function is now + defined as `updateStatus(Color)` * Added `disabled` parameter to automatically disable editor on initial load * Fixed white background color appearing sometimes when pressing backspace on text -* Added `useHybridComposition` parameter in case devs want to disable this behavior (improves animations of app) +* Added `useHybridComposition` parameter in case devs want to disable this behavior (improves + animations of app) * [WEB] Fixed editor height being 0 when `initialText` is `null` (@dab246) * Migrated example to Android embedding V2 * Removed woff fonts to allow iOS App Store submissions ## [2.4.0] - 2021-10-30 + * Improved color picker - * Added scrollable support to picker - * Fixed issue where keyboard would disappear and prevent users from selecting a new color + * Added scrollable support to picker + * Fixed issue where keyboard would disappear and prevent users from selecting a new color * Added support for getting selected text in Flutter Web (`controller.getSelectedTextWeb()`) * Added support for spellcheck * Added support for custom options in summernote initialization @@ -26,6 +100,7 @@ * Updated dependencies and fixed flutter_colorpicker dependency error (@eliudio) ## [2.3.0] - 2021-09-09 + * Potentially fixed bad state error for `stream.first` * Fixed Summernote-@-Mention not inserting text after selecting the dropdown item * Fixed whitespace after @ sign when inserting a mention @@ -41,208 +116,273 @@ NOTE: If you are on Flutter Beta+, you must use `dependency_overrides` in `pubsp ```yaml dependency_overrides: - flutter_colorpicker: ^0.5.0 + flutter_colorpicker: ^0.5.0 ``` ## [2.2.0+1] - 2021-06-15 (BETA) + * Updated `flutter_colorpicker` to the latest version to fix deprecations on Flutter beta+ * [NOTE] Do not use this version on Flutter stable! ## [2.2.0] - 2021-06-14 + * Fixed null safety warnings due to latest `file_picker` version * Potentially fixed editor controller creating a new instance on widget rebuild * Fixed issue where custom HTML files would have custom JS replaced with built-in JS * Fixed darkMode not applying when `filePath` is used on Android * Fixed "null" text showing as the hint when no hint is given * Added new `onChangeSelection` callback that passes the editor settings whenever the user changes -their current selection (e.g. tap on a different word, create a new node, select text, etc) + their current selection (e.g. tap on a different word, create a new node, select text, etc) * Added support for custom JS injection on Flutter Web * Fixed minor bug with automatic height adjustment on mobile -* Added new `ToolbarType.nativeExpandable` which allows the user to switch between the -scrollview or gridview toolbar on the fly -* Support setting the `inputmode` for the editor, which changes the virtual keyboard display on mobile devices (e.g. number pad, email keyboard, etc) +* Added new `ToolbarType.nativeExpandable` which allows the user to switch between the + scrollview or gridview toolbar on the fly +* Support setting the `inputmode` for the editor, which changes the virtual keyboard display on + mobile devices (e.g. number pad, email keyboard, etc) * [BREAKING] renamed `onChange` callback to `onChangeContent` * [BREAKING] disabled a lot of the buttons by default, now only around half of the editor buttons -are enabled to improve the UX. You can still re-enable the rest if you want. + are enabled to improve the UX. You can still re-enable the rest if you want. * [BREAKING] min Flutter version requirement bumped to 2.2.0 ## [2.1.1] - 2021-05-22 + * Fixed bottom overflow error on `AlertDialog`s if the screen size is small * Fixed `StyleButtons(style: false)` would not remove the style dropdown * Fixed JS/Dart communication hiccup on Web (make sure `postMessage` data is not null) * Code cleanup ## [2.1.0+1] - 2021-05-11 + * Hotfix for `copyWith` not defined for `ScrollBehavior` in v2.1.0 ## [2.1.0] - 2021-05-10 + * Fixed `setState` and `Stream.first` error on page dispose * Fixed height adjustment not working * Fixed `getText` on Web -* Improved dropdown UX when `ToolbarPosition.belowEditor` by opening upwards and making it scrollable after a certain height +* Improved dropdown UX when `ToolbarPosition.belowEditor` by opening upwards and making it + scrollable after a certain height ## [2.0.1] - 2021-04-28 + * Added support for setting custom `UserScript`s on the webview (mobile only) -* Added support for customizing the context menu (menu when user selects text) for the webview (mobile only) -* Added `LongPressGestureRecognizer` to the webview to allow users to select text via a long press (mobile only) - * You can set the duration before the long press is recognized via `HtmlEditorOptions > mobileLongPressDuration` -* Added support for placing the toolbar wherever using `HtmlToolbarOptions > toolbarPosition: ToolbarPosition.custom` -* See the README if you'd like to use any of these new features. `UserScript` and the context menu customization have external documentation via flutter_inappwebview - the docs are linked in the README. +* Added support for customizing the context menu (menu when user selects text) for the webview ( + mobile only) +* Added `LongPressGestureRecognizer` to the webview to allow users to select text via a long press ( + mobile only) + * You can set the duration before the long press is recognized + via `HtmlEditorOptions > mobileLongPressDuration` +* Added support for placing the toolbar wherever + using `HtmlToolbarOptions > toolbarPosition: ToolbarPosition.custom` +* See the README if you'd like to use any of these new features. `UserScript` and the context menu + customization have external documentation via flutter_inappwebview - the docs are linked in the + README. ## [2.0.0+1] - 2021-04-22 -* Transitioned to fully native controls! These are extremely customizable and have much better UX than the previous controls. + +* Transitioned to fully native controls! These are extremely customizable and have much better UX + than the previous controls. * [BREAKING] refactored a lot of options into separate constructors * [BREAKING] refactored toolbar classes, so toolbar customizations will need updating * Added a bunch of interceptors and callbacks for button presses * Added the ability to make custom buttons and set their positions * Added native support for numerous Summernote plugins - * [BREAKING] removed all Summernote plugins except Summernote @ Mention. The package now supports the majority of plugins out of the box. - * Reduced package size by removing the Summernote plugin files - * Reduced size further by using a stripped-down version of Summernote @ Mention libs + * [BREAKING] removed all Summernote plugins except Summernote @ Mention. The package now + supports the majority of plugins out of the box. + * Reduced package size by removing the Summernote plugin files + * Reduced size further by using a stripped-down version of Summernote @ Mention libs * Added `execCommand` to controller to help you create custom toolbar buttons * Improved automatic height adjustment * Bumped dependencies * [BREAKING] Require Flutter 2.0.0+ * As always, see the README for full documentation on these changes -* See the [Migration Guide](https://github.com/tneotia/html-editor-enhanced/wiki/v2.0.0-Migration-Guide) for help migrating your v1.x.x widget code +* See + the [Migration Guide](https://github.com/tneotia/html-editor-enhanced/wiki/v2.0.0-Migration-Guide) + for help migrating your v1.x.x widget code ## [1.8.0] - 2021-04-07 -* Add support for `getSuggestionsMobile` (Summernote @ Mentions Plugin) - allows you to programatically return the list of mentions. - * Only supported on mobile. - * [BREAKING] renamed `mentions` to `mentionsWeb` as a result of this change + +* Add support for `getSuggestionsMobile` (Summernote @ Mentions Plugin) - allows you to + programatically return the list of mentions. + * Only supported on mobile. + * [BREAKING] renamed `mentions` to `mentionsWeb` as a result of this change * Added support for the remainder of Summernote callbacks: - * `onBeforeCommand` - * `onChangeCodeview` - * `onDialogShown` - * `onImageUploadError` - * `onMouseDown` - * `onMouseUp` - * `onScroll` - * See the README for how these work. + * `onBeforeCommand` + * `onChangeCodeview` + * `onDialogShown` + * `onImageUploadError` + * `onMouseDown` + * `onMouseUp` + * `onScroll` + * See the README for how these work. * Added a few new functions: - * recalculateHeight(): recalculates the editor height and applies it - * addNotification(): adds a notification bar to the bottom of the editor in a specified style with specified text - * removeNotification(): removes the current notification from the bottom of the editor + * recalculateHeight(): recalculates the editor height and applies it + * addNotification(): adds a notification bar to the bottom of the editor in a specified style + with specified text + * removeNotification(): removes the current notification from the bottom of the editor * Fixed blank space at the bottom of the editor when `showBottomToolbar: false` * Fixed 'Android resource linking failed' (bumped flutter_inappwebview to 5.3.1+1) ## [1.7.1] - 2021-03-26 -* Fixed bug where initial text would not be inserted and default toolbar would be shown regardless of editor options + +* Fixed bug where initial text would not be inserted and default toolbar would be shown regardless + of editor options * Significantly improved keyboard height detection (detect when keyboard comes up and goes down) -* Adjusted HTML processing algorithm to fix issues where `"` and `'` would not be properly escaped on HTML insertion - * Added `processNewLineAsBr` - this will replace any `\n` in the input string to `
` rather than the default `""` - * Applied processing to `setHint()` and `insertHtml()` functions +* Adjusted HTML processing algorithm to fix issues where `"` and `'` would not be properly escaped + on HTML insertion + * Added `processNewLineAsBr` - this will replace any `\n` in the input string to `
` rather + than the default `""` + * Applied processing to `setHint()` and `insertHtml()` functions * Added support for returning the file's base64 data in `onImageUpload` and `onFileUpload` - * Now you can use `MultipartFile.fromBytes()` to upload to server - [example](https://github.com/tneotia/html-editor-enhanced#example-for-onimageupload-and-onimagelinkinsert) + * Now you can use `MultipartFile.fromBytes()` to upload to + server - [example](https://github.com/tneotia/html-editor-enhanced#example-for-onimageupload-and-onimagelinkinsert) * Added support for `onFileUploadError` and `onFileLinkInsert` (Summernote File plugin) * Added support for `maximumFileSize` (Summernote File plugin) * See the README for more details on these changes ## [1.7.0+1] - 2021-03-22 + * Fixed `type 'double' is not a subtype of type 'int?' in type cast` on iOS - * By extension this fixes the `adjustHeightForKeyboard` not working on iOS -* Fixed `Bad state: Cannot add new events after calling close` exception when disposing the page containing the editor -* Fixed web page not found when inserting a video URL (see [here](https://github.com/summernote/summernote/issues/3252)) + * By extension this fixes the `adjustHeightForKeyboard` not working on iOS +* Fixed `Bad state: Cannot add new events after calling close` exception when disposing the page + containing the editor +* Fixed web page not found when inserting a video URL ( + see [here](https://github.com/summernote/summernote/issues/3252)) ## [1.7.0] - 2021-03-17 + * [BREAKING]: - * Refactored `height`, `autoAdjustHeight`, `decoration`, `showBottomToolbar`, and `darkMode` into new `HtmlEditorOptions` class - see README for how to migrate - * Removed 'Summernote Classes' plugin - * Sorry for all the breaking changes lately - I think I've finally figured out how I want to do the API design so there should be far less in future releases + * Refactored `height`, `autoAdjustHeight`, `decoration`, `showBottomToolbar`, and `darkMode` + into new `HtmlEditorOptions` class - see README for how to migrate + * Removed 'Summernote Classes' plugin + * Sorry for all the breaking changes lately - I think I've finally figured out how I want to do + the API design so there should be far less in future releases * Added `onImageUpload` callback that fires when an image is inserted via `` * Added `onImageLinkInsert` callback that fires when an image is inserted via URL -* Added `shouldEnsureVisible` that scrolls the editor into view when it is focused or text is typed, kind of like `TextField`s -* Added `adjustHeightForKeyboard` (default true) that adjusts the editor's height when the keyboard is active to ensure no content is cut off by the keyboard +* Added `shouldEnsureVisible` that scrolls the editor into view when it is focused or text is typed, + kind of like `TextField`s +* Added `adjustHeightForKeyboard` (default true) that adjusts the editor's height when the keyboard + is active to ensure no content is cut off by the keyboard * Added `filePath` which allows you to provide a completely custom HTML file to load -* If you plan on using any of the above, it is highly recommend looking at the README for more details and examples. -* Removed disabled scroll feature since it prevented the editor from scrolling even when the editor content was larger than the height +* If you plan on using any of the above, it is highly recommend looking at the README for more + details and examples. +* Removed disabled scroll feature since it prevented the editor from scrolling even when the editor + content was larger than the height * Code cleanup ## [1.6.0] - 2021-03-13 + * [BREAKING] removed `dispose()` method on controller - * The editor no longer uses a `Stream` to get text and therefore nothing needs to be disposed + * The editor no longer uses a `Stream` to get text and therefore nothing needs to be disposed * Added `onInit` callback that fires once the editor is ready to function and accept JS * Added a few new parameters: - * `autoAdjustHeight` - for `HtmlEditor`: default true, automatically adjusts the height of the editor to make sure scrolling is not necessary - * `processInputHtml` - for `HtmlEditorController`: processes input HTML (e.g. new lines become `
`) - * `processOutputHtml` - for `HtmlEditorController`: processes output HTML (e.g. `


` becomes `""`) + * `autoAdjustHeight` - for `HtmlEditor`: default true, automatically adjusts the height of the + editor to make sure scrolling is not necessary + * `processInputHtml` - for `HtmlEditorController`: processes input HTML (e.g. new lines + become `
`) + * `processOutputHtml` - for `HtmlEditorController`: processes output HTML (e.g. `


` + becomes `""`) * Added more plugins: - * Summernote Case Converter - * Summernote List Styles - * Summernote RTL - * Summernote @ Mention - * Summernote Codewrapper - * Summernote File - * See the README for more details. + * Summernote Case Converter + * Summernote List Styles + * Summernote RTL + * Summernote @ Mention + * Summernote Codewrapper + * Summernote File + * See the README for more details. * Added shim for dart:ui to remove the `ui.PlatformViewRegistry not found` error -* Added the summernote-no-plugins.html file to load a de-bloated HTML file when no plugins are active +* Added the summernote-no-plugins.html file to load a de-bloated HTML file when no plugins are + active * Fixed bug where two editors would be initialized in the same webview in some cases * Reduced the size of assets to ~650kb - ~300kb summernote libs, ~350kb plugin libs * Code cleanup ## [1.5.0+1] - 2021-03-10 + * Fixed getText() returning null on mobile for any device ## [1.5.0] - 2021-03-01 + * Nullsafety preview -* Added Flutter's Hybrid Composition to the HTML Editor. This significantly improves the keyboard experience on Android. +* Added Flutter's Hybrid Composition to the HTML Editor. This significantly improves the keyboard + experience on Android. ## [1.4.0] - 2021-03-01 -* [BREAKING] removed `HtmlParser` for calling methods, instead you now must pass an `HtmlEditorController` to the plugin (like a `TextField`). All methods are accessible from that controller. See the usage section in the README for an example. - * This allows you to have multiple independent editors on a page, whereas earlier the package would not know which editor the method should be called on. -* Add support for certain Summernote plugins from [Summernote Awesome](https://github.com/summernote/awesome-summernote). See the README for details on the API and the currently supported plugins. + +* [BREAKING] removed `HtmlParser` for calling methods, instead you now must pass + an `HtmlEditorController` to the plugin (like a `TextField`). All methods are accessible from that + controller. See the usage section in the README for an example. + * This allows you to have multiple independent editors on a page, whereas earlier the package + would not know which editor the method should be called on. +* Add support for certain Summernote plugins + from [Summernote Awesome](https://github.com/summernote/awesome-summernote). See the README for + details on the API and the currently supported plugins. * Nullsafety pre-release coming soon. ## [1.3.0] - 2021-02-23 + * Add official support for Flutter Web * Add support for modifying the toolbar options. See the README for details on the API. * Add support for a native dark mode -* Removed image_picker plugin and image button in toolbar because users can insert images via the image button in Summernote - * [BREAKING] Removed the `imageWidth` and `useBottomSheet` params due to the above change +* Removed image_picker plugin and image button in toolbar because users can insert images via the + image button in Summernote + * [BREAKING] Removed the `imageWidth` and `useBottomSheet` params due to the above change ## [1.2.0+1] - 2021-02-20 + * Add support for accessing `InAppWebViewController` via a getter * Add support for inserting files via the editor dialog itself * Add methods: - * toggle code view - * enable/disable editor - * undo/redo - * inserting plaintext/HTML/images/links + * toggle code view + * enable/disable editor + * undo/redo + * inserting plaintext/HTML/images/links * Add callbacks: - * onChange - * onEnter - * onFocus/onBlur/onBlurCodeview - * onKeyUp/onKeyDown - * onPaste + * onChange + * onEnter + * onFocus/onBlur/onBlurCodeview + * onKeyUp/onKeyDown + * onPaste * Downgraded dependencies to non-nullsafety to prevent errors -* Updated docs and example app to showcase new features, refer to those for info on the above changes +* Updated docs and example app to showcase new features, refer to those for info on the above + changes ## [1.1.1] - 2021-02-19 + * Minor update to add documentation to code and completely refactor/reorganize code ## [1.1.0] - 2021-02-19 + * Switch webview dependency to `flutter_inappwebview` -* Remove localserver, instead get Summernote HTML directly from assets (improves performance and loading speeds) +* Remove localserver, instead get Summernote HTML directly from assets (improves performance and + loading speeds) * [BREAKING] Switch to `StatelessWidget` - * You no longer need a `GlobalKey` for the `HtmlEditorState`. All of the methods are static and can be called like so: + * You no longer need a `GlobalKey` for the `HtmlEditorState`. All of the methods are static and + can be called like so: ```dart HtmlEditor.setEmpty(); ``` * Fix deprecations and update dependencies ## Flutter HTML Editor changes by xrb21 + ## [1.0.1] - 2020-05-07 + * Update Readme usage for iOS ## [1.0.0] - 2020-05-07 + * fixing iOS blank screen * fixing text hint ## [0.0.2+1] - 2020-05-02 + * fixing path packages ## [0.0.2] - 2020-05-02 + * Change link repo ## [0.0.1] - 2020-05-02 + * Initial Release \ No newline at end of file diff --git a/README.md b/README.md index 7dce292a..f2202616 100644 --- a/README.md +++ b/README.md @@ -481,9 +481,11 @@ Notes: You can use these files from the package to avoid adding more asset files: ```html - - - + + + + ``` See the example HTML file [below](#example-html-for-filepath) for an actual example. @@ -848,7 +850,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; class _ExampleState extends State { final HtmlEditorController controller = HtmlEditorController(); @@ -950,9 +952,9 @@ class _ExampleState extends State { Summernote Text Editor HTML - - - + + + diff --git a/analysis_options.yaml b/analysis_options.yaml index d4fcc1ad..e69de29b 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -1 +0,0 @@ -include: package:pedantic/analysis_options.yaml \ No newline at end of file diff --git a/example/android/build.gradle b/example/android/build.gradle index 714549c2..7849bedc 100644 --- a/example/android/build.gradle +++ b/example/android/build.gradle @@ -6,7 +6,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.1.0' + classpath 'com.android.tools.build:gradle:7.4.1' classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" } } @@ -26,6 +26,6 @@ subprojects { project.evaluationDependsOn(':app') } -task clean(type: Delete) { +tasks.register("clean", Delete) { delete rootProject.buildDir } diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties index bc6a58af..cfe88f69 100644 --- a/example/android/gradle/wrapper/gradle-wrapper.properties +++ b/example/android/gradle/wrapper/gradle-wrapper.properties @@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-6.7-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-7.6.1-all.zip diff --git a/example/lib/main.dart b/example/lib/main.dart index 85057082..aa69f9b6 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -1,7 +1,10 @@ +import 'dart:developer'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:file_picker/file_picker.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart' as inApp; +import 'package:get/get.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; void main() => runApp(HtmlEditorExampleApp()); @@ -14,8 +17,128 @@ class HtmlEditorExampleApp extends StatelessWidget { theme: ThemeData(), darkTheme: ThemeData.dark(), home: HtmlEditorExample(title: 'Flutter HTML Editor Example'), + // home: MyApp2(title: 'Flutter HTML Editor Example'), + ); + } +} + +class MyApp2 extends StatefulWidget { + final String title; + + MyApp2({Key? key, required this.title}) : super(key: key); + + @override + State createState() => _MyApp2State(); +} + +class _MyApp2State extends State { + final HtmlEditorController controller1 = HtmlEditorController(); + inApp.InAppWebViewController controller = + inApp.InAppWebViewController(0123, inApp.InAppWebView()); + + final controller2 = HtmlEditorController(); + + @override + void initState() { + super.initState(); + } + + Future _latexToHtml(String latex, editorController) async { + const breakPoint = 'break'; + var mathMl = + 'xxxxxx'; + + var a = await controller2.mathMlToLatex( + mathMl.replaceAll('', breakPoint), context); + for (var value in a.split('break')) { + log(value.trim(), name: 'latex'); + } + log(a, name: 'MathMl'); + return a; + } + + @override + Widget build(BuildContext context) { + return Scaffold( + floatingActionButton: FloatingActionButton(onPressed: () { + (_latexToHtml('{x}', controller)); + }), + body: Stack( + children: [ + SingleChildScrollView( + child: Column( + children: [ + tb(controller1), + ], + ), + ), + ], + ), + appBar: AppBar( + title: Text(this.widget.title), + ), ); } + + Widget tb(HtmlEditorController controller) { + var isVisible = false.obs; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Obx( + () => isVisible.value + ? ToolbarWidget( + controller: controller, + htmlToolbarOptions: HtmlToolbarOptions( + toolbarType: kIsWeb + ? ToolbarType.nativeGrid + : ToolbarType.nativeScrollable, + toolbarPosition: ToolbarPosition + .custom, //required to place toolbar anywhere! + //other options + ), + callbacks: null) + : IconButton( + onPressed: () { + controller.insertHtml( + r'yy'); + isVisible.value = true; + }, + icon: Icon(Icons.functions_outlined)), + ), + //other widgets here + HtmlEditor( + controller: controller, + callbacks: Callbacks( + onBlur: () { + print('onBlur'); + isVisible.value = false; + }, + onNavigationRequestMobile: (s) async { + print('on NavReq to $s'); + return NavigationActionPolicy.ALLOW; + }, + onDialogShown: () => print('onDialogOpen'), + onFocus: () { + print('onFocus'); + isVisible.value = true; + }, + ), + htmlEditorOptions: HtmlEditorOptions( + hint: 'Your text here...', + shouldEnsureVisible: true, + //initialText: "

text content initial, if any

", + ), + htmlToolbarOptions: HtmlToolbarOptions( + toolbarPosition: + ToolbarPosition.custom, // required to place toolbar anywhere! + + //other options + ), + otherOptions: OtherOptions(height: 550), + ), + ]); + } } class HtmlEditorExample extends StatefulWidget { @@ -31,6 +154,17 @@ class _HtmlEditorExampleState extends State { String result = ''; final HtmlEditorController controller = HtmlEditorController(); + Future _latexToHtml(String latex) async { + const breakPoint = 'break'; + var a = await controller.mathMlToLatex( + latex.replaceAll('', breakPoint), context); + for (var value in a.split('break')) { + log(value.trim(), name: 'latex'); + } + log(a, name: 'MathMl'); + return a; + } + @override Widget build(BuildContext context) { return GestureDetector( @@ -74,32 +208,10 @@ class _HtmlEditorExampleState extends State { //initialText: "

text content initial, if any

", ), htmlToolbarOptions: HtmlToolbarOptions( - toolbarPosition: ToolbarPosition.aboveEditor, //by default - toolbarType: ToolbarType.nativeScrollable, //by default - onButtonPressed: - (ButtonType type, bool? status, Function? updateStatus) { - print( - "button '${describeEnum(type)}' pressed, the current selected status is $status"); - return true; - }, - onDropdownChanged: (DropdownType type, dynamic changed, - Function(dynamic)? updateSelectedItem) { - print( - "dropdown '${describeEnum(type)}' changed to $changed"); - return true; - }, - mediaLinkInsertInterceptor: - (String url, InsertFileType type) { - print(url); - return true; - }, - mediaUploadInterceptor: - (PlatformFile file, InsertFileType type) async { - print(file.name); //filename - print(file.size); //size in bytes - print(file.extension); //file extension (eg jpeg or mp4) - return true; - }, + toolbarPosition: ToolbarPosition.aboveEditor, + //by default + toolbarType: ToolbarType.nativeScrollable, + //by default ), otherOptions: OtherOptions(height: 550), callbacks: Callbacks(onBeforeCommand: (String? currentHtml) { @@ -136,7 +248,7 @@ class _HtmlEditorExampleState extends State { },*/ onImageUploadError: (FileUpload? file, String? base64Str, UploadError error) { - print(describeEnum(error)); + print((error.name)); print(base64Str ?? ''); if (file != null) { print(file.name); @@ -184,10 +296,11 @@ class _HtmlEditorExampleState extends State { style: TextButton.styleFrom( backgroundColor: Colors.blueGrey), onPressed: () { - controller.undo(); + controller.insertHtmlStringWithLatex( + r'

Hello

\(\sqrt{x} e \pi \)

'); }, - child: - Text('Undo', style: TextStyle(color: Colors.white)), + child: Text('insert mathMl', + style: TextStyle(color: Colors.white)), ), SizedBox( width: 16, @@ -195,11 +308,13 @@ class _HtmlEditorExampleState extends State { TextButton( style: TextButton.styleFrom( backgroundColor: Colors.blueGrey), - onPressed: () { - controller.clear(); + onPressed: () async { + var text = await controller.getText(); + var res = await _latexToHtml(text); + log(res, name: 'result'); }, - child: - Text('Reset', style: TextStyle(color: Colors.white)), + child: Text('Get Latex', + style: TextStyle(color: Colors.white)), ), SizedBox( width: 16, @@ -209,7 +324,11 @@ class _HtmlEditorExampleState extends State { backgroundColor: Theme.of(context).colorScheme.secondary), onPressed: () async { - var txt = await controller.getText(); + // var txt = await controller.getHtmlStringWithLatex(context); + var txt = + await controller.getHtmlStringWithLatex(context); + print(txt); + // print(res); if (txt.contains('src=\"data:')) { txt = ''; @@ -231,10 +350,10 @@ class _HtmlEditorExampleState extends State { backgroundColor: Theme.of(context).colorScheme.secondary), onPressed: () { - controller.redo(); + controller.insertLatex(r'\(\sqrt{x}\)'); }, child: Text( - 'Redo', + 'insert latex', style: TextStyle(color: Colors.white), ), ), diff --git a/example/lib/two_editors.dart b/example/lib/two_editors.dart new file mode 100644 index 00000000..eee38188 --- /dev/null +++ b/example/lib/two_editors.dart @@ -0,0 +1,199 @@ +import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; + +class EditorWithFocusChange extends StatefulWidget { + const EditorWithFocusChange(); + + @override + createState() => _EditorWithFocusChangeState(); +} + +class _EditorWithFocusChangeState extends State { + final HtmlEditorController controller = HtmlEditorController(); + + @override + Widget build(BuildContext context) { + return Column( + children: [ + VisibleToolbar(controller: controller), + HtmlEditor( + controller: controller, + htmlEditorOptions: HtmlEditorOptions( + hint: 'Your text here...', + shouldEnsureVisible: true, + //initialText: "

text content initial, if any

", + ), + htmlToolbarOptions: HtmlToolbarOptions( + toolbarPosition: ToolbarPosition.custom, + // toolbarType: ToolbarType.nativeScrollable, + // onButtonPressed: + // (ButtonType type, bool? status, Function? updateStatus) { + // print( + // "button '${(type.name)}' pressed, the current selected status is $status"); + // return true; + // }, + // onDropdownChanged: (DropdownType type, dynamic changed, + // Function(dynamic)? updateSelectedItem) { + // print("dropdown '${(type.name)}' changed to $changed"); + // return true; + // }, + // mediaLinkInsertInterceptor: (String url, InsertFileType type) { + // print(url); + // return true; + // }, + // mediaUploadInterceptor: (PlatformFile file, InsertFileType type) async { + // print(file.name); //filename + // print(file.size); //size in bytes + // print(file.extension); //file extension (eg jpeg or mp4) + // return true; + // }, + ), + otherOptions: OtherOptions(height: 550), + plugins: [ + SummernoteAtMention( + getSuggestionsMobile: (String value) { + var mentions = ['test1', 'test2', 'test3']; + return mentions + .where((element) => element.contains(value)) + .toList(); + }, + mentionsWeb: ['test1', 'test2', 'test3'], + onSelect: (String value) { + print(value); + }, + ), + ], + ), + ], + ); + } +} + +class VisibleToolbar extends StatefulWidget { + const VisibleToolbar({required this.controller}); + + final HtmlEditorController controller; + + @override + State createState() => _VisibleToolbarState(); +} + +class _VisibleToolbarState extends State { + bool _isVisible = false; + + @override + Widget build(BuildContext context) { + return Visibility( + visible: _isVisible, + child: ToolbarWidget( + controller: widget.controller, + htmlToolbarOptions: HtmlToolbarOptions( + toolbarPosition: ToolbarPosition.custom, + toolbarType: ToolbarType.nativeScrollable, + defaultToolbarButtons: const [ + StyleButtons(), + FontSettingButtons(fontSizeUnit: false, fontName: false), + FontButtons(clearAll: false), + ColorButtons(highlightColor: false), + ListButtons(listStyles: false), + ParagraphButtons( + textDirection: false, + lineHeight: false, + caseConverter: false, + alignJustify: false), + InsertButtons( + video: false, + link: false, + audio: false, + table: true, + hr: true, + otherFile: false), + ], + ), + callbacks: Callbacks( + onBeforeCommand: (String? currentHtml) { + print('html before change is $currentHtml'); + }, + onChangeContent: (String? changed) { + print('content changed to $changed'); + }, + onChangeCodeview: (String? changed) { + print('code changed to $changed'); + }, + onChangeSelection: (EditorSettings settings) { + print('parent element is ${settings.parentElement}'); + print('font name is ${settings.fontName}'); + }, + onDialogShown: () { + print('dialog shown'); + }, + onEnter: () { + print('enter/return pressed'); + }, + onFocus: () { + setState(() { + _isVisible = true; + }); + print('editor focused'); + }, + onBlur: () { + setState(() { + _isVisible = false; + }); + print('editor unfocused'); + }, + onBlurCodeview: () { + print('codeview either focused or unfocused'); + }, + onInit: () { + print('init'); + }, + //this is commented because it overrides the default Summernote handlers + /*onImageLinkInsert: (String? url) { + print(url ?? "unknown url"); + }, + onImageUpload: (FileUpload file) async { + print(file.name); + print(file.size); + print(file.type); + print(file.base64); + },*/ + onImageUploadError: + (FileUpload? file, String? base64Str, UploadError error) { + print((error.name)); + print(base64Str ?? ''); + if (file != null) { + print(file.name); + print(file.size); + print(file.type); + } + }, + onKeyDown: (int? keyCode) { + print('$keyCode key downed'); + print( + 'current character count: ${widget.controller.characterCount}'); + }, + onKeyUp: (int? keyCode) { + print('$keyCode key released'); + }, + onMouseDown: () { + print('mouse downed'); + }, + onMouseUp: () { + print('mouse released'); + }, + onNavigationRequestMobile: (String url) { + print(url); + return NavigationActionPolicy.ALLOW; + }, + onPaste: () { + print('pasted into editor'); + }, + onScroll: () { + print('editor scrolled'); + }, + ), + ), + ); + } +} diff --git a/example/pubspec.lock b/example/pubspec.lock index b98a159b..fb5f6e94 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -1,83 +1,110 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "0.3.4+2" cupertino_icons: dependency: "direct main" description: name: cupertino_icons - url: "https://pub.dartlang.org" + sha256: d57953e10f9f8327ce64a508a355f0b1ec902193f66288e8cb5070e7c47eeb2d + url: "https://pub.dev" source: hosted - version: "1.0.5" + version: "1.0.6" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.3" file_picker: dependency: transitive description: name: file_picker - url: "https://pub.dartlang.org" + sha256: "04a7b85852255759fd3010530cafac250eaa1f8202546670834d25057bb3251a" + url: "https://pub.dev" source: hosted - version: "5.2.5" + version: "8.0.0" flex_color_picker: dependency: transitive description: name: flex_color_picker - url: "https://pub.dartlang.org" + sha256: "5c846437069fb7afdd7ade6bf37e628a71d2ab0787095ddcb1253bf9345d5f3a" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.4.1" flex_seed_scheme: dependency: transitive description: name: flex_seed_scheme - url: "https://pub.dartlang.org" + sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.5.0" flutter: dependency: "direct main" description: flutter @@ -87,58 +114,87 @@ packages: dependency: transitive description: name: flutter_inappwebview - url: "https://pub.dartlang.org" + sha256: d198297060d116b94048301ee6749cd2e7d03c1f2689783f52d210a6b7aba350 + url: "https://pub.dev" source: hosted - version: "5.7.2+3" + version: "5.8.0" flutter_keyboard_visibility: dependency: transitive description: name: flutter_keyboard_visibility - url: "https://pub.dartlang.org" + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.0" flutter_keyboard_visibility_linux: dependency: transitive description: name: flutter_keyboard_visibility_linux - url: "https://pub.dartlang.org" + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_keyboard_visibility_macos: dependency: transitive description: name: flutter_keyboard_visibility_macos - url: "https://pub.dartlang.org" + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_keyboard_visibility_platform_interface: dependency: transitive description: name: flutter_keyboard_visibility_platform_interface - url: "https://pub.dartlang.org" + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_keyboard_visibility_web: dependency: transitive description: name: flutter_keyboard_visibility_web - url: "https://pub.dartlang.org" + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_keyboard_visibility_windows: dependency: transitive description: name: flutter_keyboard_visibility_windows - url: "https://pub.dartlang.org" + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" source: hosted version: "1.0.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_math_fork: + dependency: transitive + description: + name: flutter_math_fork + sha256: "94bee4642892a94939af0748c6a7de0ff8318feee588379dcdfea7dc5cba06c8" + url: "https://pub.dev" + source: hosted + version: "0.7.2" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f + url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.5" flutter_test: dependency: "direct dev" description: flutter @@ -149,83 +205,197 @@ packages: description: flutter source: sdk version: "0.0.0" - html_editor_enhanced: + get: + dependency: "direct main" + description: + name: get + sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + holding_gesture: + dependency: transitive + description: + name: holding_gesture + sha256: "6d12a991c498357f9c8a532656facf97c47858be9a7249d5caaa84707aecc052" + url: "https://pub.dev" + source: hosted + version: "1.1.0" + html_editor_enhanced_fork_latex: dependency: "direct main" description: path: ".." relative: true source: path - version: "2.5.1" + version: "4.0.0" infinite_listview: dependency: transitive description: name: infinite_listview - url: "https://pub.dartlang.org" + sha256: f6062c1720eb59be553dfa6b89813d3e8dd2f054538445aaa5edaddfa5195ce6 + url: "https://pub.dev" source: hosted version: "1.1.0" - js: + intl: dependency: transitive description: - name: js - url: "https://pub.dartlang.org" + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.18.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + math_expressions: + dependency: transitive + description: + name: math_expressions + sha256: "3576593617c3870d75728a751f6ec6e606706d44e363f088ac394b5a28a98064" + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "2.4.0" + math_keyboard: + dependency: "direct main" + description: + name: math_keyboard + sha256: "7a7a644ce4313f31b74bc31c9d522dbdc08e5462dfa7beb4d0973cd4232e9ba3" + url: "https://pub.dev" + source: hosted + version: "0.2.0" meta: dependency: transitive description: name: meta - url: "https://pub.dartlang.org" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.11.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" numberpicker: dependency: transitive description: name: numberpicker - url: "https://pub.dartlang.org" + sha256: "4c129154944b0f6b133e693f8749c3f8bfb67c4d07ef9dcab48b595c22d1f156" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.2" - pedantic: + version: "1.9.0" + path_parsing: dependency: transitive description: - name: pedantic - url: "https://pub.dartlang.org" + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" + source: hosted + version: "5.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" pointer_interceptor: dependency: transitive description: name: pointer_interceptor - url: "https://pub.dartlang.org" + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" + url: "https://pub.dev" + source: hosted + version: "0.10.1+2" + pointer_interceptor_ios: + dependency: transitive + description: + name: pointer_interceptor_ios + sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 + url: "https://pub.dev" + source: hosted + version: "0.10.1" + pointer_interceptor_platform_interface: + dependency: transitive + description: + name: pointer_interceptor_platform_interface + sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" + url: "https://pub.dev" + source: hosted + version: "0.10.0+1" + pointer_interceptor_web: + dependency: transitive + description: + name: pointer_interceptor_web + sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" + url: "https://pub.dev" + source: hosted + version: "0.10.2+1" + provider: + dependency: transitive + description: + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + url: "https://pub.dev" source: hosted - version: "0.9.3+3" + version: "6.1.1" sky_engine: dependency: transitive description: flutter @@ -235,65 +405,162 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" + source: hosted + version: "0.6.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79 + url: "https://pub.dev" + source: hosted + version: "1.1.5" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "1.1.5" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca" + url: "https://pub.dev" + source: hosted + version: "1.1.5" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" visibility_detector: dependency: transitive description: name: visibility_detector - url: "https://pub.dartlang.org" + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + webview_flutter: + dependency: transitive + description: + name: webview_flutter + sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" + url: "https://pub.dev" + source: hosted + version: "4.4.2" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf" + url: "https://pub.dev" + source: hosted + version: "3.12.1" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76 + url: "https://pub.dev" + source: hosted + version: "3.9.4" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + xml: + dependency: transitive + description: + name: xml + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "6.2.2" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index 5e1c4814..72cf9a63 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -6,13 +6,14 @@ description: Demonstrates how to use the html_editor_enhanced plugin. publish_to: 'none' # Remove this line if you wish to publish to pub.dev environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.15.0 <3.0.0' dependencies: flutter: sdk: flutter - - html_editor_enhanced: + get: ^4.0.0 + math_keyboard: 0.2.0 + html_editor_enhanced_fork_latex: # When depending on this package from a real application you should use: # html_editor_enhanced: ^x.y.z # See https://dart.dev/tools/pub/dependencies#version-constraints diff --git a/lib/html_editor.dart b/lib/html_editor.dart index c11e5afc..c5c2c9f1 100644 --- a/lib/html_editor.dart +++ b/lib/html_editor.dart @@ -1,24 +1,23 @@ library html_editor; -export 'package:html_editor_enhanced/src/widgets/toolbar_widget.dart'; -export 'package:html_editor_enhanced/utils/callbacks.dart'; -export 'package:html_editor_enhanced/utils/toolbar.dart'; -export 'package:html_editor_enhanced/utils/plugins.dart'; -export 'package:html_editor_enhanced/utils/file_upload_model.dart'; -export 'package:html_editor_enhanced/utils/options.dart'; -export 'package:html_editor_enhanced/utils/utils.dart' - hide setState, intersperse, getRandString; - -export 'package:html_editor_enhanced/src/html_editor_unsupported.dart' - if (dart.library.html) 'package:html_editor_enhanced/src/html_editor_web.dart' - if (dart.library.io) 'package:html_editor_enhanced/src/html_editor_mobile.dart'; - -export 'package:html_editor_enhanced/src/html_editor_controller_unsupported.dart' - if (dart.library.html) 'package:html_editor_enhanced/src/html_editor_controller_web.dart' - if (dart.library.io) 'package:html_editor_enhanced/src/html_editor_controller_mobile.dart'; - -export 'package:html_editor_enhanced/utils/shims/flutter_inappwebview_fake.dart' +export 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_unsupported.dart' + if (dart.library.html) 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_web.dart' + if (dart.library.io) 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_mobile.dart'; +export 'package:html_editor_enhanced_fork_latex/src/html_editor_unsupported.dart' + if (dart.library.html) 'package:html_editor_enhanced_fork_latex/src/html_editor_web.dart' + if (dart.library.io) 'package:html_editor_enhanced_fork_latex/src/html_editor_mobile.dart'; +export 'package:html_editor_enhanced_fork_latex/src/widgets/custom_html_editor.dart'; +export 'package:html_editor_enhanced_fork_latex/src/widgets/math_keyboard_dialog.dart'; +export 'package:html_editor_enhanced_fork_latex/src/widgets/toolbar_widget.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/callbacks.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/file_upload_model.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/options.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/plugins.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/shims/flutter_inappwebview_fake.dart' if (dart.library.io) 'package:flutter_inappwebview/flutter_inappwebview.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/toolbar.dart'; +export 'package:html_editor_enhanced_fork_latex/utils/utils.dart' + hide setState, intersperse, getRandString; /// Defines the 3 different cases for file insertion failing enum UploadError { unsupportedFile, exceededMaxSize, jsException } @@ -72,6 +71,7 @@ enum ButtonType { otherFile, table, hr, + fn, fullscreen, codeview, undo, diff --git a/lib/src/html_editor_controller_mobile.dart b/lib/src/html_editor_controller_mobile.dart index 7210d11c..92571cba 100644 --- a/lib/src/html_editor_controller_mobile.dart +++ b/lib/src/html_editor_controller_mobile.dart @@ -1,9 +1,16 @@ +import 'dart:async'; +import 'dart:developer'; + import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/src/html_editor_controller_unsupported.dart' - as unsupported; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_unsupported.dart' +as unsupported; +import 'package:html_editor_enhanced_fork_latex/utils/custom_math_field_controller.dart'; +import 'package:math_keyboard/math_keyboard.dart'; +import 'package:webview_flutter/webview_flutter.dart'; /// Controller for mobile class HtmlEditorController extends unsupported.HtmlEditorController { @@ -11,6 +18,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { this.processInputHtml = true, this.processNewLineAsBr = false, this.processOutputHtml = true, + this.mathField, }); /// Toolbar widget state to call various methods. For internal use only. @@ -38,6 +46,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { /// The default value is true. @override final bool processOutputHtml; + final MathField? mathField; /// Manages the [InAppWebViewController] for the [HtmlEditorController] InAppWebViewController? _editorController; @@ -195,7 +204,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { @override void reloadWeb() { throw Exception( - 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart and check kIsWeb before calling this function'); + 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart and check kIsWeb before calling this function'); } /// Resets the height of the editor back to the original if it was changed to @@ -224,7 +233,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { void addNotification(String html, NotificationType notificationType) async { await _evaluateJavascript(source: """ \$('.note-status-output').html( - '
$html
' + '
$html
' ); """); recalculateHeight(); @@ -265,7 +274,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { return result; } else { throw Exception( - 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart'); + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart'); } } @@ -288,4 +297,199 @@ class HtmlEditorController extends unsupported.HtmlEditorController { /// Internal function to insert table on Web @override void insertTable(String dimensions) {} + + @override + openMathDialog(BuildContext context) async { + final c = CustomMathFieldEditingController(); + if (!kIsWeb) { + this.clearFocus(); + } + await showDialog( + context: context, + builder: (context) => MathKeyboardDialog( + controller: c, + mathField: this.mathField, + )); + if (!kIsWeb) { + this.setFocus(); + } + var math = c.texString; + if (math != '') { + var texAsFun = c.texStringAsFun; + var result = await latexToHtml(math); + result = '$result'; + latexMap.addAll({ + result: texAsFun, + }); + this.addToHashMap(result, texAsFun); + this.insertHtml(result); + this.insertText(' '); + } + } + + @override + Future latexToHtml(String latex) async { + latex = latex.replaceAll('\\', '\\\\'); + var res = await editorController!.callAsyncJavaScript( + functionBody: r''' + async function func(){ + const mathlive = await import("https://unpkg.com/mathlive?module"); + const mathML = mathlive.convertLatexToMathMl('\$\$''' + '$latex' + r'''\$\$'); + return(mathML); + }; + var p = await func(); + return p; + ''', + arguments: {'latex': latex}); + log(res.toString()); + log(res?.toMap().toString() ?? ''); + return res!.value.toString(); + } + + @override + Future mathMlToLatex(String mathMl, BuildContext context) async { + String result = ''; + late BuildContext dialogContext; + Completer completer = Completer(); + final webViewController = WebViewController() + ..setJavaScriptMode(JavaScriptMode.unrestricted) + ..setOnConsoleMessage((message) async { + log( + message.message, + name: 'ON_CONSOLE_MESSAGE', + ); + result = message.message; + completer.complete(result); + await Future.delayed(Duration(milliseconds: 150)); + Navigator.pop(dialogContext); + }) + ..loadHtmlString(_getHtmlMathMlToLatex(mathMl)); + showDialog( + context: context, + builder: (context) { + dialogContext = context; + return Stack( + children: [ + Center(child: CircularProgressIndicator()), + Visibility( + visible: false, + child: WebViewWidget( + controller: webViewController, + )), + ], + ); + }); + return completer.future; + } + + insertLatex(String latex) async { + var html = await latexToHtml(latex); + this.insertHtml('$html'); + } + + Future getHtmlStringWithLatex(context) async { + var txt = await getText(); + final reg = RegExp('', multiLine: true); + var tags = []; + var res = txt.split(reg); + print('result = $res'); + String latexString = ''; + const bp = 'break'; + int index = 0; + res.forEach((element) { + if (element.contains(r'')) { + var split = element.split(r''); + var after = split.last; + element = '${split.first}'; + latexString = '$latexString$element'; + // tags.add(latexMap[element + // .replaceAll('π', 'pi') + // .replaceAll('π', 'pi') + // .replaceAll(' ', '') + // .trim()] ?? + // ''); + tags.add('LATEX#'); + if (after.isNotEmpty) tags.add(after); + } else { + tags.add(element); + } + }); + latexString = latexString.replaceAll('', bp); + log(latexString, name: 'latex string'); + var latexRes = await mathMlToLatex(latexString, context); + log(latexRes, name: 'mathMlToLatex'); + var latexList = latexRes.split('break'); + bool isTrue = true; + + var tag = ''; + tags.forEach((element) { + if (element.isNotEmpty) tag = '$tag$element'; + }); + while (isTrue) { + if (tag.contains('LATEX#')) { + tag = tag.replaceFirst('LATEX#', '\\(${latexList[index++]}\\)'); + } else { + isTrue = false; + } + } + return tag.replaceAll('

', ''); + } + + Future insertHtmlStringWithLatex(String latex) async { + var txt = latex; + final reg = RegExp(r'\(', multiLine: true); + var tags = []; + var res = txt.split(reg); + print('result = $res'); + String latexString = ''; + const bp = 'break'; + int index = 0; + res.forEach((element) { + if (element.contains(r'\)')) { + var split = element.split(r'\)'); + var after = split.last; + element = '\\(${split.first}\\)'; + latexString = '$latexString$element'; + tags.add('LATEX#'); + if (after.isNotEmpty) tags.add(after); + } else { + tags.add(element); + } + }); + latexString = latexString.replaceAll('\\)\\(', bp); + log(latexString, name: 'latex string'); + var latexRes = await latexToHtml( + latexString, + ); + log(latexRes, name: 'LatexToMathMl'); + var latexList = latexRes.split('break'); + bool isTrue = true; + var tag = ''; + tags.forEach((element) { + if (element.isNotEmpty) tag = '$tag$element'; + }); + while (isTrue) { + if (tag.contains('LATEX#')) { + tag = tag.replaceFirst('LATEX#', + '${latexList[index++]}'); + } else { + isTrue = false; + } + } + this.insertHtml(tag.replaceAll('

', '')); + return tag.replaceAll('

', ''); + } + + String _getHtmlMathMlToLatex(String mathMl) => ''' + + ' + ' + '''; } diff --git a/lib/src/html_editor_controller_unsupported.dart b/lib/src/html_editor_controller_unsupported.dart index 618cbf1a..b1ed75f5 100644 --- a/lib/src/html_editor_controller_unsupported.dart +++ b/lib/src/html_editor_controller_unsupported.dart @@ -1,4 +1,9 @@ -import 'package:html_editor_enhanced/html_editor.dart'; +import 'dart:async'; +import 'dart:collection'; + +import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:math_keyboard/math_keyboard.dart'; import 'package:meta/meta.dart'; /// Fallback controller (should never be used) @@ -7,8 +12,60 @@ class HtmlEditorController { this.processInputHtml = true, this.processNewLineAsBr = false, this.processOutputHtml = true, + this.mathField, }); + final HashMap latexMap = HashMap(); + + openMathDialog(BuildContext context) async {} + + latexToHtml(String latex) {} + + Future mathMlToLatex(String mathMl, BuildContext context) { + throw Exception('UnImplemented'); + } + + void addToHashMap(String key, String value) { + latexMap.addAll({ + key + .replaceAll('π', 'pi') + .replaceAll('π', 'pi') + .replaceAll(' ', '') + .trim(): value, + }); + } + + Future getHtmlStringWithLatex(context) async { + var txt = await getText(); + final reg = RegExp('', multiLine: true); + var tags = []; + var res = txt.split(reg); + print('result = $res'); + + res.forEach((element) { + if (element.contains(r'')) { + var split = element.split(r''); + var after = split.last; + element = '${split.first}'; + tags.add(latexMap[element + .replaceAll('π', 'pi') + .replaceAll('π', 'pi') + .trim()] ?? + ''); + if (after.isNotEmpty) tags.add(after); + } else { + tags.add(element); + } + }); + var tag = ''; + tags.forEach((element) { + if (element.isNotEmpty) tag = '$tag$element'; + }); + return tag; + } + + insertLatex(String latex) {} + /// Toolbar widget state to call various methods. For internal use only. @internal ToolbarWidgetState? toolbar; @@ -31,6 +88,7 @@ class HtmlEditorController { /// /// The default value is true. final bool processOutputHtml; + final MathField? mathField; /// Internally tracks the character count in the editor int _characterCount = 0; @@ -171,4 +229,6 @@ class HtmlEditorController { /// Internal function to insert table on Web @internal void insertTable(String dimensions) {} + + insertHtmlStringWithLatex(String latex) {} } diff --git a/lib/src/html_editor_controller_web.dart b/lib/src/html_editor_controller_web.dart index 01ff3dec..0065cea1 100644 --- a/lib/src/html_editor_controller_web.dart +++ b/lib/src/html_editor_controller_web.dart @@ -3,8 +3,10 @@ import 'dart:convert'; import 'dart:html' as html; import 'package:flutter/foundation.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/src/html_editor_controller_unsupported.dart' +import 'package:flutter/material.dart'; +import 'package:flutter_inappwebview/flutter_inappwebview.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_unsupported.dart' as unsupported; import 'package:meta/meta.dart'; @@ -14,7 +16,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { this.processInputHtml = true, this.processNewLineAsBr = false, this.processOutputHtml = true, - }); + }) : super(mathField: null); /// Toolbar widget state to call various methods. For internal use only. @override @@ -187,7 +189,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { @override void clearFocus() { throw Exception( - 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart and check kIsWeb before calling this method.'); + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart and check kIsWeb before calling this method.'); } /// Resets the height of the editor back to the original if it was changed to @@ -196,7 +198,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { @override void resetHeight() { throw Exception( - 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart and check kIsWeb before calling this method.'); + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart and check kIsWeb before calling this method.'); } /// Refresh the page @@ -288,7 +290,7 @@ class HtmlEditorController extends unsupported.HtmlEditorController { _evaluateJavascriptWeb(data: { 'type': 'toIframe: addNotification', 'html': html, - 'alertType': 'alert alert-${describeEnum(notificationType)}' + 'alertType': 'alert alert-${(notificationType.name)}' }); } recalculateHeight(); @@ -323,7 +325,19 @@ class HtmlEditorController extends unsupported.HtmlEditorController { html.window.postMessage(json, '*'); } else { throw Exception( - 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart'); + 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart'); } } + + @override + openMathDialog(BuildContext context) async { + throw Exception( + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart and check kIsWeb before calling this method.'); + } + + @override + Future latexToHtml(String latex) async { + throw Exception( + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart and check kIsWeb before calling this method.'); + } } diff --git a/lib/src/html_editor_mobile.dart b/lib/src/html_editor_mobile.dart index 50faf109..0afe5ce4 100644 --- a/lib/src/html_editor_mobile.dart +++ b/lib/src/html_editor_mobile.dart @@ -1,9 +1,9 @@ -import 'package:html_editor_enhanced/html_editor.dart' - hide HtmlEditorController; -import 'package:html_editor_enhanced/src/html_editor_controller_mobile.dart'; -import 'package:html_editor_enhanced/src/widgets/html_editor_widget_mobile.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart' + hide HtmlEditorController; +import 'package:html_editor_enhanced_fork_latex/src/html_editor_controller_mobile.dart'; +import 'package:html_editor_enhanced_fork_latex/src/widgets/html_editor_widget_mobile.dart'; /// HtmlEditor class for mobile class HtmlEditor extends StatelessWidget { @@ -51,7 +51,7 @@ class HtmlEditor extends StatelessWidget { ); } else { return Text( - 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart'); + 'Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart'); } } } diff --git a/lib/src/html_editor_unsupported.dart b/lib/src/html_editor_unsupported.dart index abc6239a..a8eabf55 100644 --- a/lib/src/html_editor_unsupported.dart +++ b/lib/src/html_editor_unsupported.dart @@ -1,5 +1,5 @@ import 'package:flutter/material.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; /// Fallback HtmlEditor class (should never be called) class HtmlEditor extends StatelessWidget { diff --git a/lib/src/html_editor_web.dart b/lib/src/html_editor_web.dart index 3de5c787..81f072bf 100644 --- a/lib/src/html_editor_web.dart +++ b/lib/src/html_editor_web.dart @@ -1,7 +1,7 @@ -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/src/widgets/html_editor_widget_web.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/src/widgets/html_editor_widget_web.dart'; /// HtmlEditor class for web class HtmlEditor extends StatelessWidget { @@ -50,7 +50,7 @@ class HtmlEditor extends StatelessWidget { ); } else { return Text( - 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced/html_editor.dart'); + 'Non-Flutter Web environment detected, please make sure you are importing package:html_editor_enhanced_fork_latex/html_editor.dart'); } } } diff --git a/lib/src/widgets/custom_html_editor.dart b/lib/src/widgets/custom_html_editor.dart new file mode 100644 index 00000000..cb9f6a04 --- /dev/null +++ b/lib/src/widgets/custom_html_editor.dart @@ -0,0 +1,169 @@ +// ignore_for_file: avoid_print + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + +import '../../html_editor.dart'; + +class CustomHtmlEditorWidget extends StatelessWidget { + const CustomHtmlEditorWidget({required this.controller, double? height}) + : _height = height ?? 500; + final HtmlEditorController controller; + final double _height; + + Widget _htmlWidget() { + return HtmlEditor( + controller: controller, + htmlEditorOptions: const HtmlEditorOptions( + hint: 'Your text here...', + shouldEnsureVisible: true, + //initialText: "

text content initial, if any

", + ), + htmlToolbarOptions: HtmlToolbarOptions( + toolbarPosition: ToolbarPosition.aboveEditor, + defaultToolbarButtons: [ + const StyleButtons(), + const FontSettingButtons(fontSizeUnit: false), + const FontButtons(clearAll: false), + const ColorButtons(), + const ListButtons(listStyles: false), + const ParagraphButtons( + textDirection: false, lineHeight: false, caseConverter: false), + const InsertButtons( + video: false, + audio: false, + table: true, + hr: true, + fn: true, + otherFile: false), + ], + //by default + toolbarType: ToolbarType.nativeExpandable, + //by default + onButtonPressed: + (ButtonType type, bool? status, Function? updateStatus) { + print( + "button '${type.name}' pressed, the current selected status is $status"); + return true; + }, + onDropdownChanged: (DropdownType type, dynamic changed, + Function(dynamic)? updateSelectedItem) { + print("dropdown '${type.name}' changed to $changed"); + return true; + }, + mediaLinkInsertInterceptor: (String url, InsertFileType type) { + print(url); + return true; + }, + mediaUploadInterceptor: (PlatformFile file, InsertFileType type) async { + if (kDebugMode) { + print(file.name); + } //filename + print(file.size); //size in bytes + print(file.extension); //file extension (eg jpeg or mp4) + return true; + }, + ), + otherOptions: OtherOptions(height: _height), + callbacks: Callbacks(onBeforeCommand: (String? currentHtml) { + print('html before change is $currentHtml'); + }, onChangeContent: (String? changed) { + print('content changed to $changed'); + }, onChangeCodeview: (String? changed) { + print('code changed to $changed'); + }, onChangeSelection: (EditorSettings settings) { + print('parent element is ${settings.parentElement}'); + print('font name is ${settings.fontName}'); + }, onDialogShown: () { + print('dialog shown'); + }, onEnter: () { + print('enter/return pressed'); + }, onFocus: () { + print('editor focused'); + }, onBlur: () { + print('editor unfocused'); + }, onBlurCodeview: () { + print('codeview either focused or unfocused'); + }, onInit: () { + print('init'); + }, + //this is commented because it overrides the default Summernote handlers + /*onImageLinkInsert: (String? url) { + print(url ?? "unknown url"); + }, + onImageUpload: (FileUpload file) async { + print(file.name); + print(file.size); + print(file.type); + print(file.base64); + },*/ + onImageUploadError: + (FileUpload? file, String? base64Str, UploadError error) { + print((error.name)); + print(base64Str ?? ''); + if (file != null) { + print(file.name); + print(file.size); + print(file.type); + } + }, onKeyDown: (int? keyCode) { + print('$keyCode key downed'); + print('current character count: ${controller.characterCount}'); + }, onKeyUp: (int? keyCode) { + print('$keyCode key released'); + }, onMouseDown: () { + print('mouse downed'); + }, onMouseUp: () { + print('mouse released'); + }, onNavigationRequestMobile: (String url) { + print(url); + return NavigationActionPolicy.ALLOW; + }, onPaste: () { + print('pasted into editor'); + }, onScroll: () { + print('editor scrolled'); + }), + plugins: [ + SummernoteAtMention( + getSuggestionsMobile: (String value) { + var mentions = ['test1', 'test2', 'test3']; + return mentions + .where((element) => element.contains(value)) + .toList(); + }, + mentionsWeb: ['test1', 'test2', 'test3'], + onSelect: (String value) { + print(value); + }), + ], + ); + } + + @override + Widget build(BuildContext context) { + return _htmlWidget(); + } +} + +const tableTex = r''' + + \begin{array} { | l | l | l | } +\hline \text { Year } & \begin{array} { l } +\text { Number of U.S. } \\ +\text { farms (in } \\ +\text { millions) } +\end{array} & \begin{array} { l } +\text { Average size of } \\ +\text { U.S. farms } \\ +\text { (acres) } +\end{array} \\ +\hline 1950 & 5.6 & 234 \\ +\hline 1960 & 4.0 & 330 \\ +\hline 1970 & 2.9 & 399 \\ +\hline 1980 & 2.4 & 441 \\ +\hline 1990 & 2.1 & 478 \\ +\hline 2000 & 2.2 & 439 \\ +\hline +\end{array} + '''; diff --git a/lib/src/widgets/html_editor_widget_mobile.dart b/lib/src/widgets/html_editor_widget_mobile.dart index a2458ca8..f2c064a6 100644 --- a/lib/src/widgets/html_editor_widget_mobile.dart +++ b/lib/src/widgets/html_editor_widget_mobile.dart @@ -8,9 +8,9 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; import 'package:flutter_keyboard_visibility/flutter_keyboard_visibility.dart'; -import 'package:html_editor_enhanced/html_editor.dart' +import 'package:html_editor_enhanced_fork_latex/html_editor.dart' hide NavigationActionPolicy, UserScript, ContextMenu; -import 'package:html_editor_enhanced/utils/utils.dart'; +import 'package:html_editor_enhanced_fork_latex/utils/utils.dart'; import 'package:visibility_detector/visibility_detector.dart'; /// The HTML Editor widget itself, for mobile (uses InAppWebView) @@ -72,9 +72,10 @@ class _HtmlEditorWidgetMobileState extends State { filePath = widget.htmlEditorOptions.filePath!; } else if (widget.plugins.isEmpty) { filePath = - 'packages/html_editor_enhanced/assets/summernote-no-plugins.html'; + 'packages/html_editor_enhanced_fork_latex/assets/summernote-no-plugins.html'; } else { - filePath = 'packages/html_editor_enhanced/assets/summernote.html'; + filePath = + 'packages/html_editor_enhanced_fork_latex/assets/summernote.html'; } super.initState(); } @@ -180,9 +181,8 @@ class _HtmlEditorWidgetMobileState extends State { print(message.message); }, onWindowFocus: (controller) async { - if (widget.htmlEditorOptions.shouldEnsureVisible && - Scrollable.of(context) != null) { - await Scrollable.of(context)!.position.ensureVisible( + if (widget.htmlEditorOptions.shouldEnsureVisible) { + await Scrollable.of(context).position.ensureVisible( context.findRenderObject()!, ); } @@ -451,13 +451,13 @@ class _HtmlEditorWidgetMobileState extends State { "document.onselectionchange = onSelectionChange; console.log('done');"); await controller.evaluateJavascript( source: - "document.getElementsByClassName('note-editable')[0].setAttribute('inputmode', '${describeEnum(widget.htmlEditorOptions.inputType)}');"); + "document.getElementsByClassName('note-editable')[0].setAttribute('inputmode', '${(widget.htmlEditorOptions.inputType.name)}');"); if ((Theme.of(context).brightness == Brightness.dark || widget.htmlEditorOptions.darkMode == true) && widget.htmlEditorOptions.darkMode != false) { //todo fix for iOS (https://github.com/pichillilorenzo/flutter_inappwebview/issues/695) var darkCSS = - ''; + ''; await controller.evaluateJavascript( source: "\$('head').append('$darkCSS');"); } @@ -526,9 +526,8 @@ class _HtmlEditorWidgetMobileState extends State { controller.addJavaScriptHandler( handlerName: 'onChangeContent', callback: (contents) { - if (widget.htmlEditorOptions.shouldEnsureVisible && - Scrollable.of(context) != null) { - Scrollable.of(context)!.position.ensureVisible( + if (widget.htmlEditorOptions.shouldEnsureVisible) { + Scrollable.of(context).position.ensureVisible( context.findRenderObject()!, ); } diff --git a/lib/src/widgets/html_editor_widget_web.dart b/lib/src/widgets/html_editor_widget_web.dart index c348920f..2bae694d 100644 --- a/lib/src/widgets/html_editor_widget_web.dart +++ b/lib/src/widgets/html_editor_widget_web.dart @@ -1,15 +1,14 @@ -export 'dart:html'; - import 'dart:convert'; +// ignore: avoid_web_libraries_in_flutter +import 'dart:html' as html; -import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/utils/utils.dart'; -// ignore: avoid_web_libraries_in_flutter -import 'dart:html' as html; -import 'package:html_editor_enhanced/utils/shims/dart_ui.dart' as ui; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/utils/shims/dart_ui.dart' as ui; +import 'package:html_editor_enhanced_fork_latex/utils/utils.dart'; + +export 'dart:html'; /// The HTML Editor widget itself, for web (uses IFrameElement) class HtmlEditorWidget extends StatefulWidget { @@ -187,7 +186,7 @@ class _HtmlEditorWidgetWebState extends State { widget.htmlEditorOptions.darkMode == true) && widget.htmlEditorOptions.darkMode != false) { darkCSS = - ''; + ''; } var jsCallbacks = ''; if (widget.callbacks != null) { @@ -241,7 +240,7 @@ class _HtmlEditorWidgetWebState extends State { window.parent.postMessage(JSON.stringify({"view": "$createdViewId", "type": "toDart: htmlHeight", "height": height}), "*"); } if (data["type"].includes("setInputType")) { - document.getElementsByClassName('note-editable')[0].setAttribute('inputmode', '${describeEnum(widget.htmlEditorOptions.inputType)}'); + document.getElementsByClassName('note-editable')[0].setAttribute('inputmode', '${(widget.htmlEditorOptions.inputType).name}'); } if (data["type"].includes("setText")) { \$('#summernote-2').summernote('code', data["text"]); @@ -447,7 +446,7 @@ class _HtmlEditorWidgetWebState extends State { """; var filePath = - 'packages/html_editor_enhanced/assets/summernote-no-plugins.html'; + 'packages/html_editor_enhanced_fork_latex/assets/summernote-no-plugins.html'; if (widget.htmlEditorOptions.filePath != null) { filePath = widget.htmlEditorOptions.filePath!; } @@ -457,11 +456,11 @@ class _HtmlEditorWidgetWebState extends State { .replaceFirst('', headString) .replaceFirst('', summernoteScripts) .replaceFirst('"jquery.min.js"', - '"assets/packages/html_editor_enhanced/assets/jquery.min.js"') + '"assets/packages/html_editor_enhanced_fork_latex/assets/jquery.min.js"') .replaceFirst('"summernote-lite.min.css"', - '"assets/packages/html_editor_enhanced/assets/summernote-lite.min.css"') + '"assets/packages/html_editor_enhanced_fork_latex/assets/summernote-lite.min.css"') .replaceFirst('"summernote-lite.min.js"', - '"assets/packages/html_editor_enhanced/assets/summernote-lite.min.js"'); + '"assets/packages/html_editor_enhanced_fork_latex/assets/summernote-lite.min.js"'); if (widget.callbacks != null) addJSListener(widget.callbacks!); final iframe = html.IFrameElement() ..width = MediaQuery.of(widget.initBC).size.width.toString() //'800' @@ -513,9 +512,8 @@ class _HtmlEditorWidgetWebState extends State { widget.callbacks!.onChangeContent != null) { widget.callbacks!.onChangeContent!.call(data['contents']); } - if (widget.htmlEditorOptions.shouldEnsureVisible && - Scrollable.of(context) != null) { - Scrollable.of(context)!.position.ensureVisible( + if (widget.htmlEditorOptions.shouldEnsureVisible) { + Scrollable.of(context).position.ensureVisible( context.findRenderObject()!, duration: const Duration(milliseconds: 100), curve: Curves.easeIn); diff --git a/lib/src/widgets/math_keyboard_dialog.dart b/lib/src/widgets/math_keyboard_dialog.dart new file mode 100644 index 00000000..287a6339 --- /dev/null +++ b/lib/src/widgets/math_keyboard_dialog.dart @@ -0,0 +1,84 @@ +import 'dart:developer'; + +import 'package:flutter/material.dart'; +import 'package:html_editor_enhanced_fork_latex/utils/custom_math_field_controller.dart'; +import 'package:math_keyboard/math_keyboard.dart'; + +class MathKeyboardDialog extends StatelessWidget { + MathKeyboardDialog({required this.controller, this.mathField}) { + if (mathField != null && mathField!.controller != null) { + log('', + name: 'Warning', + error: + 'do not set the math field controller as it will get ignored\n'); + } + } + + final CustomMathFieldEditingController controller; + final MathField? mathField; + + @override + Widget build(BuildContext context) { + return Dialog( + insetPadding: EdgeInsets.all(10), + child: Padding( + padding: const EdgeInsets.all(8.0), + child: Column( + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SizedBox( + width: MediaQuery.of(context).size.width, + height: 100, + child: MathField( + focusNode: mathField?.focusNode, + autofocus: mathField?.autofocus ?? true, + controller: controller, + keyboardType: + mathField?.keyboardType ?? MathKeyboardType.expression, + variables: + mathField?.variables ?? ['x', 'y', 'z', 'A', 'B', 'C'], + decoration: mathField?.decoration ?? + InputDecoration( + suffix: MouseRegion( + cursor: MaterialStateMouseCursor.clickable, + child: GestureDetector( + onTap: controller.clear, + child: const Icon( + Icons.cleaning_services_rounded, + color: Colors.grey, + ), + ), + ), + ), + onChanged: mathField?.onChanged ?? controller.setTexString, + onSubmitted: mathField?.onSubmitted, + opensKeyboard: mathField?.opensKeyboard ?? true, + ), + ), + const SizedBox(height: 15), + Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + TextButton( + onPressed: () { + Navigator.pop(context, ''); + print(controller.texStringAsFun); + }, + child: const Text('Close'), + ), + TextButton( + onPressed: () { + Navigator.pop(context, controller.texStringAsFun); + print(controller.texStringAsFun); + }, + child: const Text('Save'), + ), + ], + ), + ], + ), + ), + ); + } +} diff --git a/lib/src/widgets/toolbar_widget.dart b/lib/src/widgets/toolbar_widget.dart index 2e33f27f..3a188e15 100644 --- a/lib/src/widgets/toolbar_widget.dart +++ b/lib/src/widgets/toolbar_widget.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:convert'; import 'package:file_picker/file_picker.dart'; @@ -5,8 +6,8 @@ import 'package:flex_color_picker/flex_color_picker.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/utils/utils.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/utils/utils.dart'; import 'package:numberpicker/numberpicker.dart'; import 'package:pointer_interceptor/pointer_interceptor.dart'; @@ -1120,7 +1121,7 @@ class ToolbarWidgetState extends State { newColor = color; }, title: Text('Choose a Color', - style: Theme.of(context).textTheme.headline6), + style: Theme.of(context).textTheme.titleLarge), width: 40, height: 40, spacing: 0, @@ -1758,6 +1759,7 @@ class ToolbarWidgetState extends State { t.picture || t.link || t.hr || + t.fn || t.table)) { toolbarChildren.add(ToggleButtons( constraints: BoxConstraints.tightFor( @@ -1872,7 +1874,7 @@ class ToolbarWidgetState extends State { style: TextStyle( color: Theme.of(context) .textTheme - .bodyText1 + .bodyLarge ?.color)), ), ], @@ -1986,7 +1988,7 @@ class ToolbarWidgetState extends State { style: TextStyle( color: Theme.of(context) .textTheme - .bodyText1 + .bodyLarge ?.color)), ), suffixIcon: result != null @@ -2146,7 +2148,7 @@ class ToolbarWidgetState extends State { style: TextStyle( color: Theme.of(context) .textTheme - .bodyText1 + .bodyLarge ?.color)), ), suffixIcon: result != null @@ -2298,7 +2300,7 @@ class ToolbarWidgetState extends State { style: TextStyle( color: Theme.of(context) .textTheme - .bodyText1 + .bodyLarge ?.color)), ), suffixIcon: result != null @@ -2450,7 +2452,7 @@ class ToolbarWidgetState extends State { style: TextStyle( color: Theme.of(context) .textTheme - .bodyText1 + .bodyLarge ?.color)), ), suffixIcon: result != null @@ -2600,6 +2602,14 @@ class ToolbarWidgetState extends State { widget.controller.insertHtml('
'); } } + if (t.getIcons()[index].icon == Icons.functions) { + var proceed = await widget.htmlToolbarOptions.onButtonPressed + ?.call(ButtonType.fn, null, null) ?? + true; + if (proceed) { + await widget.controller.openMathDialog(context); + } + } }, isSelected: List.filled(t.getIcons().length, false), children: t.getIcons(), @@ -2998,4 +3008,48 @@ class ToolbarWidgetState extends State { } return toolbarChildren; } +// +// openMathDialog() async { +// final c = CustomMathFieldEditingController(); +// if (!kIsWeb) { +// widget.controller.clearFocus(); +// } +// await showDialog( +// context: context, +// builder: (context) => MathKeyboardDialog( +// controller: c, +// mathField: widget.controller.mathField, +// )); +// if (!kIsWeb) { +// widget.controller.setFocus(); +// } +// var math = c.texString; +// if (math != '') { +// var texAsFun = c.texStringAsFun; +// var result = await _latexToHtml(math.replaceAll('\\', '\\\\')); +// result = '$result'; +// _latexMap.addAll({ +// result: texAsFun, +// }); +// widget.controller.addToHashMap(result, texAsFun); +// widget.controller.insertHtml(result); +// widget.controller.insertText(' '); +// } +// } +// +// Future _latexToHtml(String latex) async { +// await _webController.runJavaScript(''' +// (async () => { +// try { +// const mathlive = await import("https://unpkg.com/mathlive?module"); +// const mathML = mathlive.convertLatexToMathMl('\$\$$latex\$\$'); +// MathMLChannel.postMessage(mathML); +// } catch (error) { +// console.error('Error:', error); +// } +// })(); +// '''); +// +// return _completer.future; +// } } diff --git a/lib/utils/callbacks.dart b/lib/utils/callbacks.dart index 366a6a94..daefdbd9 100644 --- a/lib/utils/callbacks.dart +++ b/lib/utils/callbacks.dart @@ -1,6 +1,6 @@ import 'dart:async'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; /// Manages all the callback functions the library provides class Callbacks { diff --git a/lib/utils/custom_math_field_controller.dart b/lib/utils/custom_math_field_controller.dart new file mode 100644 index 00000000..223d6cc0 --- /dev/null +++ b/lib/utils/custom_math_field_controller.dart @@ -0,0 +1,35 @@ +import 'package:flutter/material.dart'; +import 'package:math_keyboard/math_keyboard.dart'; + +class CustomMathFieldEditingController extends MathFieldEditingController { + /// Constructs a [MathKeyboardViewModel]. + CustomMathFieldEditingController() { + currentNode = root; + currentNode.setCursor(); + } + + String texString = ''; + + void setTexString(String str) { + texString = str; + } + + String get texStringAsFun => '\\($texString\\)'; + + @override + String currentEditingValue({bool placeholderWhenEmpty = true}) { + currentNode.removeCursor(); + // Store the expression as a TeX string. + final expression = root.buildTeXString( + // By passing null as the cursor color here, we are asserting + // that the cursor is not part of the tree in a way. + cursorColor: Colors.transparent, + placeholderWhenEmpty: placeholderWhenEmpty, + ); + currentNode.setCursor(); + final colorString = + '#${(Colors.transparent.value & 0xFFFFFF).toRadixString(16).padLeft(6, '0')}'; + var text = '\\textcolor{$colorString}{\\cursor}'; + return expression.replaceAll(text, ''); + } +} diff --git a/lib/utils/options.dart b/lib/utils/options.dart index 8212be6c..6ad3a959 100644 --- a/lib/utils/options.dart +++ b/lib/utils/options.dart @@ -3,7 +3,7 @@ import 'dart:collection'; import 'package:file_picker/file_picker.dart'; import 'package:flutter/material.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; /// Options that modify the editor and its behavior class HtmlEditorOptions { diff --git a/lib/utils/plugins.dart b/lib/utils/plugins.dart index 7fe4b8a7..14c58869 100644 --- a/lib/utils/plugins.dart +++ b/lib/utils/plugins.dart @@ -34,7 +34,7 @@ class SummernoteAtMention extends Plugins { @override String getHeadString() { - return ''; + return ''; } @override diff --git a/lib/utils/toolbar.dart b/lib/utils/toolbar.dart index 91b491fd..2e71b2b5 100644 --- a/lib/utils/toolbar.dart +++ b/lib/utils/toolbar.dart @@ -1,3 +1,4 @@ +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; /// Abstract class that all the toolbar classes extend @@ -153,6 +154,7 @@ class InsertButtons extends Toolbar { final bool otherFile; final bool table; final bool hr; + final bool fn; const InsertButtons({ this.link = true, @@ -162,6 +164,7 @@ class InsertButtons extends Toolbar { this.otherFile = false, this.table = true, this.hr = true, + this.fn = true, }); List getIcons() { @@ -173,6 +176,7 @@ class InsertButtons extends Toolbar { if (otherFile) icons.add(Icon(Icons.attach_file)); if (table) icons.add(Icon(Icons.table_chart_outlined)); if (hr) icons.add(Icon(Icons.horizontal_rule)); + if (fn && !kIsWeb) icons.add(Icon(Icons.functions)); return icons; } } diff --git a/lib/utils/utils.dart b/lib/utils/utils.dart index 8d9c6c8d..43100f9f 100644 --- a/lib/utils/utils.dart +++ b/lib/utils/utils.dart @@ -5,8 +5,8 @@ import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; -import 'package:html_editor_enhanced/html_editor.dart'; -import 'package:html_editor_enhanced/utils/shims/dart_ui.dart'; +import 'package:html_editor_enhanced_fork_latex/html_editor.dart'; +import 'package:html_editor_enhanced_fork_latex/utils/shims/dart_ui.dart'; /// small function to always check if mounted before running setState() void setState( @@ -491,6 +491,7 @@ class _DropdownRouteResult { class _MenuLimits { const _MenuLimits(this.top, this.bottom, this.height, this.scrollOffset); + final double top; final double bottom; final double height; @@ -845,6 +846,7 @@ class _DropdownButtonState extends State> _DropdownRoute? _dropdownRoute; Orientation? _lastOrientation; FocusNode? _internalNode; + FocusNode? get focusNode => widget.focusNode ?? _internalNode; bool _hasPrimaryFocus = false; late Map> _actionMap; @@ -949,7 +951,7 @@ class _DropdownButtonState extends State> } TextStyle? get _textStyle => - widget.style ?? Theme.of(context).textTheme.subtitle1; + widget.style ?? Theme.of(context).textTheme.titleMedium; void _handleTap() { final textDirection = Directionality.maybeOf(context); @@ -1009,7 +1011,7 @@ class _DropdownButtonState extends State> double get _denseButtonHeight { final fontSize = _textStyle!.fontSize ?? - Theme.of(context).textTheme.subtitle1!.fontSize!; + Theme.of(context).textTheme.titleMedium!.fontSize!; return max(fontSize, max(widget.iconSize, _kDenseButtonHeight)); } @@ -1090,8 +1092,7 @@ class _DropdownButtonState extends State> hintIndex = items.length; items.add(DefaultTextStyle( style: _textStyle!.copyWith(color: Theme.of(context).hintColor), - child: IgnorePointer( - ignoringSemantics: false, + child: ExcludeSemantics( child: displayedHint, ), )); diff --git a/pubspec.lock b/pubspec.lock index 88f4be47..9e50104b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1,76 +1,102 @@ # Generated by pub # See https://dart.dev/tools/pub/glossary#lockfile packages: + args: + dependency: transitive + description: + name: args + sha256: bf9f5caeea8d8fe6721a9c358dd8a5c1947b27f1cfaa18b39c301273594919e6 + url: "https://pub.dev" + source: hosted + version: "2.6.0" async: dependency: transitive description: name: async - url: "https://pub.dartlang.org" + sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + url: "https://pub.dev" source: hosted - version: "2.9.0" + version: "2.11.0" boolean_selector: dependency: transitive description: name: boolean_selector - url: "https://pub.dartlang.org" + sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.1" characters: dependency: transitive description: name: characters - url: "https://pub.dartlang.org" + sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.3.0" clock: dependency: transitive description: name: clock - url: "https://pub.dartlang.org" + sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + url: "https://pub.dev" source: hosted version: "1.1.1" collection: dependency: transitive description: name: collection - url: "https://pub.dartlang.org" + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a + url: "https://pub.dev" + source: hosted + version: "1.18.0" + cross_file: + dependency: transitive + description: + name: cross_file + sha256: "7caf6a750a0c04effbb52a676dce9a4a592e10ad35c34d6d2d0e4811160d5670" + url: "https://pub.dev" source: hosted - version: "1.16.0" + version: "0.3.4+2" fake_async: dependency: transitive description: name: fake_async - url: "https://pub.dartlang.org" + sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + url: "https://pub.dev" source: hosted version: "1.3.1" ffi: dependency: transitive description: name: ffi - url: "https://pub.dartlang.org" + sha256: "16ed7b077ef01ad6170a3d0c57caa4a112a38d7a2ed5602e0aca9ca6f3d98da6" + url: "https://pub.dev" source: hosted - version: "2.0.1" + version: "2.1.3" file_picker: dependency: "direct main" description: name: file_picker - url: "https://pub.dartlang.org" + sha256: "04a7b85852255759fd3010530cafac250eaa1f8202546670834d25057bb3251a" + url: "https://pub.dev" source: hosted - version: "5.2.5" + version: "8.0.0" flex_color_picker: dependency: "direct main" description: name: flex_color_picker - url: "https://pub.dartlang.org" + sha256: "5c846437069fb7afdd7ade6bf37e628a71d2ab0787095ddcb1253bf9345d5f3a" + url: "https://pub.dev" source: hosted - version: "3.0.2" + version: "3.4.1" flex_seed_scheme: dependency: transitive description: name: flex_seed_scheme - url: "https://pub.dartlang.org" + sha256: "4cee2f1d07259f77e8b36f4ec5f35499d19e74e17c7dce5b819554914082bc01" + url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.5.0" flutter: dependency: "direct main" description: flutter @@ -80,58 +106,87 @@ packages: dependency: "direct main" description: name: flutter_inappwebview - url: "https://pub.dartlang.org" + sha256: d198297060d116b94048301ee6749cd2e7d03c1f2689783f52d210a6b7aba350 + url: "https://pub.dev" source: hosted - version: "5.7.2+3" + version: "5.8.0" flutter_keyboard_visibility: dependency: "direct main" description: name: flutter_keyboard_visibility - url: "https://pub.dartlang.org" + sha256: "98664be7be0e3ffca00de50f7f6a287ab62c763fc8c762e0a21584584a3ff4f8" + url: "https://pub.dev" source: hosted - version: "5.4.0" + version: "6.0.0" flutter_keyboard_visibility_linux: dependency: transitive description: name: flutter_keyboard_visibility_linux - url: "https://pub.dartlang.org" + sha256: "6fba7cd9bb033b6ddd8c2beb4c99ad02d728f1e6e6d9b9446667398b2ac39f08" + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_keyboard_visibility_macos: dependency: transitive description: name: flutter_keyboard_visibility_macos - url: "https://pub.dartlang.org" + sha256: c5c49b16fff453dfdafdc16f26bdd8fb8d55812a1d50b0ce25fc8d9f2e53d086 + url: "https://pub.dev" source: hosted version: "1.0.0" flutter_keyboard_visibility_platform_interface: dependency: transitive description: name: flutter_keyboard_visibility_platform_interface - url: "https://pub.dartlang.org" + sha256: e43a89845873f7be10cb3884345ceb9aebf00a659f479d1c8f4293fcb37022a4 + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_keyboard_visibility_web: dependency: transitive description: name: flutter_keyboard_visibility_web - url: "https://pub.dartlang.org" + sha256: d3771a2e752880c79203f8d80658401d0c998e4183edca05a149f5098ce6e3d1 + url: "https://pub.dev" source: hosted version: "2.0.0" flutter_keyboard_visibility_windows: dependency: transitive description: name: flutter_keyboard_visibility_windows - url: "https://pub.dartlang.org" + sha256: fc4b0f0b6be9b93ae527f3d527fb56ee2d918cd88bbca438c478af7bcfd0ef73 + url: "https://pub.dev" source: hosted version: "1.0.0" + flutter_localizations: + dependency: transitive + description: flutter + source: sdk + version: "0.0.0" + flutter_math_fork: + dependency: transitive + description: + name: flutter_math_fork + sha256: "94bee4642892a94939af0748c6a7de0ff8318feee588379dcdfea7dc5cba06c8" + url: "https://pub.dev" + source: hosted + version: "0.7.2" flutter_plugin_android_lifecycle: dependency: transitive description: name: flutter_plugin_android_lifecycle - url: "https://pub.dartlang.org" + sha256: b068ffc46f82a55844acfa4fdbb61fad72fa2aef0905548419d97f0f95c456da + url: "https://pub.dev" + source: hosted + version: "2.0.17" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: f991fdb1533c3caeee0cdc14b04f50f0c3916f0dbcbc05237ccbe4e3c6b93f3f + url: "https://pub.dev" source: hosted - version: "2.0.7" + version: "2.0.5" flutter_test: dependency: "direct dev" description: flutter @@ -142,76 +197,190 @@ packages: description: flutter source: sdk version: "0.0.0" + get: + dependency: "direct main" + description: + name: get + sha256: "2ba20a47c8f1f233bed775ba2dd0d3ac97b4cf32fc17731b3dfc672b06b0e92a" + url: "https://pub.dev" + source: hosted + version: "4.6.5" + holding_gesture: + dependency: transitive + description: + name: holding_gesture + sha256: "6d12a991c498357f9c8a532656facf97c47858be9a7249d5caaa84707aecc052" + url: "https://pub.dev" + source: hosted + version: "1.1.0" infinite_listview: dependency: transitive description: name: infinite_listview - url: "https://pub.dartlang.org" + sha256: f6062c1720eb59be553dfa6b89813d3e8dd2f054538445aaa5edaddfa5195ce6 + url: "https://pub.dev" source: hosted version: "1.1.0" - js: + intl: dependency: transitive description: - name: js - url: "https://pub.dartlang.org" + name: intl + sha256: "3bc132a9dbce73a7e4a21a17d06e1878839ffbf975568bc875c60537824b0c4d" + url: "https://pub.dev" source: hosted - version: "0.6.4" + version: "0.18.1" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" matcher: dependency: transitive description: name: matcher - url: "https://pub.dartlang.org" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + url: "https://pub.dev" source: hosted - version: "0.12.12" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - url: "https://pub.dartlang.org" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" + url: "https://pub.dev" + source: hosted + version: "0.8.0" + math_expressions: + dependency: transitive + description: + name: math_expressions + sha256: "3576593617c3870d75728a751f6ec6e606706d44e363f088ac394b5a28a98064" + url: "https://pub.dev" source: hosted - version: "0.1.5" + version: "2.4.0" + math_keyboard: + dependency: "direct main" + description: + name: math_keyboard + sha256: "7a7a644ce4313f31b74bc31c9d522dbdc08e5462dfa7beb4d0973cd4232e9ba3" + url: "https://pub.dev" + source: hosted + version: "0.2.0" meta: dependency: "direct main" description: name: meta - url: "https://pub.dartlang.org" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 + url: "https://pub.dev" source: hosted - version: "1.8.0" + version: "1.11.0" + nested: + dependency: transitive + description: + name: nested + sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20" + url: "https://pub.dev" + source: hosted + version: "1.0.0" numberpicker: dependency: "direct main" description: name: numberpicker - url: "https://pub.dartlang.org" + sha256: "4c129154944b0f6b133e693f8749c3f8bfb67c4d07ef9dcab48b595c22d1f156" + url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" path: dependency: transitive description: name: path - url: "https://pub.dartlang.org" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + url: "https://pub.dev" source: hosted - version: "1.8.2" - pedantic: - dependency: "direct main" + version: "1.9.0" + path_parsing: + dependency: transitive description: - name: pedantic - url: "https://pub.dartlang.org" + name: path_parsing + sha256: e3e67b1629e6f7e8100b367d3db6ba6af4b1f0bb80f64db18ef1fbabd2fa9ccf + url: "https://pub.dev" source: hosted - version: "1.11.1" + version: "1.0.1" + petitparser: + dependency: transitive + description: + name: petitparser + sha256: "49392a45ced973e8d94a85fdb21293fbb40ba805fc49f2965101ae748a3683b4" + url: "https://pub.dev" + source: hosted + version: "5.1.0" plugin_platform_interface: dependency: transitive description: name: plugin_platform_interface - url: "https://pub.dartlang.org" + sha256: "4820fbfdb9478b1ebae27888254d445073732dae3d6ea81f0b7e06d5dedc3f02" + url: "https://pub.dev" source: hosted - version: "2.1.3" + version: "2.1.8" pointer_interceptor: dependency: "direct main" description: name: pointer_interceptor - url: "https://pub.dartlang.org" + sha256: "57210410680379aea8b1b7ed6ae0c3ad349bfd56fe845b8ea934a53344b9d523" + url: "https://pub.dev" + source: hosted + version: "0.10.1+2" + pointer_interceptor_ios: + dependency: transitive + description: + name: pointer_interceptor_ios + sha256: a6906772b3205b42c44614fcea28f818b1e5fdad73a4ca742a7bd49818d9c917 + url: "https://pub.dev" + source: hosted + version: "0.10.1" + pointer_interceptor_platform_interface: + dependency: transitive + description: + name: pointer_interceptor_platform_interface + sha256: "0597b0560e14354baeb23f8375cd612e8bd4841bf8306ecb71fcd0bb78552506" + url: "https://pub.dev" + source: hosted + version: "0.10.0+1" + pointer_interceptor_web: + dependency: transitive + description: + name: pointer_interceptor_web + sha256: "7a7087782110f8c1827170660b09f8aa893e0e9a61431dbbe2ac3fc482e8c044" + url: "https://pub.dev" + source: hosted + version: "0.10.2+1" + provider: + dependency: transitive + description: + name: provider + sha256: "9a96a0a19b594dbc5bf0f1f27d2bc67d5f95957359b461cd9feb44ed6ae75096" + url: "https://pub.dev" source: hosted - version: "0.9.3+3" + version: "6.1.1" sky_engine: dependency: transitive description: flutter @@ -221,65 +390,162 @@ packages: dependency: transitive description: name: source_span - url: "https://pub.dartlang.org" + sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.10.0" stack_trace: dependency: transitive description: name: stack_trace - url: "https://pub.dartlang.org" + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" + url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - url: "https://pub.dartlang.org" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.2" string_scanner: dependency: transitive description: name: string_scanner - url: "https://pub.dartlang.org" + sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde" + url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.2.0" term_glyph: dependency: transitive description: name: term_glyph - url: "https://pub.dartlang.org" + sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + url: "https://pub.dev" source: hosted version: "1.2.1" test_api: dependency: transitive description: name: test_api - url: "https://pub.dartlang.org" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" + url: "https://pub.dev" source: hosted - version: "0.4.12" + version: "0.6.1" + tuple: + dependency: transitive + description: + name: tuple + sha256: a97ce2013f240b2f3807bcbaf218765b6f301c3eff91092bcfa23a039e7dd151 + url: "https://pub.dev" + source: hosted + version: "2.0.2" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: ea8d3fc7b2e0f35de38a7465063ecfcf03d8217f7962aa2a6717132cb5d43a79 + url: "https://pub.dev" + source: hosted + version: "1.1.5" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: a5eaa5d19e123ad4f61c3718ca1ed921c4e6254238d9145f82aa214955d9aced + url: "https://pub.dev" + source: hosted + version: "1.1.5" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "15edc42f7eaa478ce854eaf1fbb9062a899c0e4e56e775dd73b7f4709c97c4ca" + url: "https://pub.dev" + source: hosted + version: "1.1.5" vector_math: dependency: transitive description: name: vector_math - url: "https://pub.dartlang.org" + sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803" + url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" visibility_detector: dependency: "direct main" description: name: visibility_detector - url: "https://pub.dartlang.org" + sha256: dd5cc11e13494f432d15939c3aa8ae76844c42b723398643ce9addb88a5ed420 + url: "https://pub.dev" + source: hosted + version: "0.4.0+2" + vm_service: + dependency: transitive + description: + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 + url: "https://pub.dev" source: hosted - version: "0.3.3" + version: "13.0.0" + web: + dependency: transitive + description: + name: web + sha256: "97da13628db363c635202ad97068d47c5b8aa555808e7a9411963c533b449b27" + url: "https://pub.dev" + source: hosted + version: "0.5.1" + webview_flutter: + dependency: "direct main" + description: + name: webview_flutter + sha256: "42393b4492e629aa3a88618530a4a00de8bb46e50e7b3993fedbfdc5352f0dbf" + url: "https://pub.dev" + source: hosted + version: "4.4.2" + webview_flutter_android: + dependency: transitive + description: + name: webview_flutter_android + sha256: "8326ee235f87605a2bfc444a4abc897f4abc78d83f054ba7d3d1074ce82b4fbf" + url: "https://pub.dev" + source: hosted + version: "3.12.1" + webview_flutter_platform_interface: + dependency: transitive + description: + name: webview_flutter_platform_interface + sha256: "6d9213c65f1060116757a7c473247c60f3f7f332cac33dc417c9e362a9a13e4f" + url: "https://pub.dev" + source: hosted + version: "2.6.0" + webview_flutter_wkwebview: + dependency: transitive + description: + name: webview_flutter_wkwebview + sha256: accdaaa49a2aca2dc3c3230907988954cdd23fed0a19525d6c9789d380f4dc76 + url: "https://pub.dev" + source: hosted + version: "3.9.4" win32: dependency: transitive description: name: win32 - url: "https://pub.dartlang.org" + sha256: "0eaf06e3446824099858367950a813472af675116bf63f008a4c2a75ae13e9cb" + url: "https://pub.dev" + source: hosted + version: "5.5.0" + xml: + dependency: transitive + description: + name: xml + sha256: "979ee37d622dec6365e2efa4d906c37470995871fe9ae080d967e192d88286b5" + url: "https://pub.dev" source: hosted - version: "3.1.3" + version: "6.2.2" sdks: - dart: ">=2.18.0 <3.0.0" - flutter: ">=3.3.0" + dart: ">=3.3.0 <4.0.0" + flutter: ">=3.19.0" diff --git a/pubspec.yaml b/pubspec.yaml index 82d4a1ad..e7433d91 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,37 +1,41 @@ -name: html_editor_enhanced +name: html_editor_enhanced_fork_latex description: HTML rich text editor for Android, iOS, and Web, using the Summernote library. Enhanced with highly customizable widget-based controls, bug fixes, callbacks, dark mode, and more. -version: 2.5.1 +version: 4.0.0 homepage: https://github.com/tneotia/html-editor-enhanced +repository: https://github.com/AhmadKhateebq/html-editor-enhanced-with-latex.git environment: - sdk: '>=2.12.0 <3.0.0' + sdk: '>=2.15.0 <4.0.0' flutter: ">=3.0.0" dependencies: flutter: sdk: flutter # webview plugin - flutter_inappwebview: ^5.7.2+3 + flutter_inappwebview: 5.8.0 # plugin to get webview's visible fraction for keyboard height adjustment - visibility_detector: ^0.3.3 + visibility_detector: ^0.4.0+2 # plugin to get when the keyboard is hidden via back (Android) # or "done" (iOS) to reset the editor's height - flutter_keyboard_visibility: ^5.4.0 + flutter_keyboard_visibility: ^6.0.0 # plugin to show a color picker for foreground/highlight color - flex_color_picker: ^3.0.2 + flex_color_picker: ^3.4.0 # plugin to get files from filesystem - file_picker: ^5.2.0+1 + file_picker: 8.0.0 # plugin to show a scrollable number picker for inserting tables - numberpicker: ^2.1.1 + numberpicker: ^2.1.2 # plugin to allow dropdowns and dialogs to be interactable when displaying over the editor # related to https://github.com/flutter/flutter/issues/54027 # pinned to 0.9.1 because of issues with CanvasKit in the latest versions - pointer_interceptor: ^0.9.3+3 + pointer_interceptor: ^0.10.1+2 # plugin to help maintain effective Dart standards - pedantic: ^1.11.1 + # plugin for @internal annotation - meta: '>=1.0.0 <2.0.0' + meta: ^1.11.0 + math_keyboard: 0.2.0 + webview_flutter: ^4.0.0 + get: ^4.0.0 dev_dependencies: flutter_test: @@ -44,15 +48,15 @@ dev_dependencies: flutter: assets: - - packages/html_editor_enhanced/assets/summernote.html - - packages/html_editor_enhanced/assets/summernote-no-plugins.html - - packages/html_editor_enhanced/assets/summernote-lite.min.css - - packages/html_editor_enhanced/assets/summernote-lite-dark.css - - packages/html_editor_enhanced/assets/summernote-lite.min.js - - packages/html_editor_enhanced/assets/jquery.min.js - - packages/html_editor_enhanced/assets/font/summernote.eot - - packages/html_editor_enhanced/assets/font/summernote.ttf - - packages/html_editor_enhanced/assets/plugins/summernote-at-mention/summernote-at-mention.js + - packages/html_editor_enhanced_fork_latex/assets/summernote.html + - packages/html_editor_enhanced_fork_latex/assets/summernote-no-plugins.html + - packages/html_editor_enhanced_fork_latex/assets/summernote-lite.min.css + - packages/html_editor_enhanced_fork_latex/assets/summernote-lite-dark.css + - packages/html_editor_enhanced_fork_latex/assets/summernote-lite.min.js + - packages/html_editor_enhanced_fork_latex/assets/jquery.min.js + - packages/html_editor_enhanced_fork_latex/assets/font/summernote.eot + - packages/html_editor_enhanced_fork_latex/assets/font/summernote.ttf + - packages/html_editor_enhanced_fork_latex/assets/plugins/summernote-at-mention/summernote-at-mention.js # This section identifies this Flutter project as a plugin project. # The 'pluginClass' and Android 'package' identifiers should not ordinarily # be modified. They are used by the tooling to maintain consistency when