From e660d0de229841f449cc829e056b302fd5bde957 Mon Sep 17 00:00:00 2001 From: hejl Date: Fri, 16 May 2025 10:37:09 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0js=E8=87=AA=E5=AE=9A=E4=B9=89?= =?UTF-8?q?=E8=A7=84=E5=88=99=E6=90=9C=E7=B4=A2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- win_text_editor/.vscode/launch.json | 25 ++ .../lib/app/components/text_editor.dart | 4 + .../content_search_controller.dart | 202 +++++++++++++--- .../content_search_service.dart | 171 +++++++++++++ .../content_search/directory_settings.dart | 4 +- .../modules/content_search/results_view.dart | 225 ++++++++++++++---- .../content_search/search_settings.dart | 24 +- win_text_editor/pubspec.lock | 58 ++++- win_text_editor/pubspec.yaml | 3 + .../flutter/generated_plugin_registrant.cc | 3 + .../windows/flutter/generated_plugins.cmake | 1 + 11 files changed, 626 insertions(+), 94 deletions(-) create mode 100644 win_text_editor/.vscode/launch.json create mode 100644 win_text_editor/lib/app/modules/content_search/content_search_service.dart diff --git a/win_text_editor/.vscode/launch.json b/win_text_editor/.vscode/launch.json new file mode 100644 index 0000000..bda458e --- /dev/null +++ b/win_text_editor/.vscode/launch.json @@ -0,0 +1,25 @@ +{ + // 使用 IntelliSense 了解相关属性。 + // 悬停以查看现有属性的描述。 + // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "win_text_editor", + "request": "launch", + "type": "dart" + }, + { + "name": "win_text_editor (profile mode)", + "request": "launch", + "type": "dart", + "flutterMode": "profile" + }, + { + "name": "win_text_editor (release mode)", + "request": "launch", + "type": "dart", + "flutterMode": "release" + } + ] +} \ No newline at end of file diff --git a/win_text_editor/lib/app/components/text_editor.dart b/win_text_editor/lib/app/components/text_editor.dart index 04b60b3..712ed16 100644 --- a/win_text_editor/lib/app/components/text_editor.dart +++ b/win_text_editor/lib/app/components/text_editor.dart @@ -151,4 +151,8 @@ class TextEditorState extends State { ), ); } + + void setContent(String content) { + _editorController.updateContent(content); + } } diff --git a/win_text_editor/lib/app/modules/content_search/content_search_controller.dart b/win_text_editor/lib/app/modules/content_search/content_search_controller.dart index 4d99fe6..c928c5a 100644 --- a/win_text_editor/lib/app/modules/content_search/content_search_controller.dart +++ b/win_text_editor/lib/app/modules/content_search/content_search_controller.dart @@ -1,6 +1,15 @@ +// content_search_controller.dart + +import 'dart:convert'; +import 'dart:io'; + import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; +import 'package:path/path.dart' as path; import 'package:win_text_editor/app/core/tab_manager.dart'; +import 'package:win_text_editor/app/providers/logger.dart'; +import 'content_search_service.dart'; +import 'package:flutter_js/flutter_js.dart'; class ContentSearchController with ChangeNotifier { final TabManager tabManager; @@ -14,8 +23,11 @@ class ContentSearchController with ChangeNotifier { bool _customRule = false; SearchMode _searchMode = SearchMode.locate; final List _results = []; + late final JavascriptRuntime _jsRuntime; - ContentSearchController({required this.tabManager}); + ContentSearchController({required this.tabManager}) { + _jsRuntime = getJavascriptRuntime(); + } // Getters String get searchQuery => _searchQuery; @@ -69,23 +81,152 @@ class ContentSearchController with ChangeNotifier { notifyListeners(); } - Future startSearch() async { + void clearResults() { results.clear(); - // 模拟搜索结果 - results.addAll([ - SearchResult( - filePath: 'lib/main.dart', - lineNumber: 42, - lineContent: 'void main() => runApp(MyApp());', - matches: const [MatchResult(start: 5, end: 9)], - ), - SearchResult( - filePath: 'lib/home_page.dart', - lineNumber: 17, - lineContent: 'class HomePage extends StatelessWidget {', - matches: const [MatchResult(start: 6, end: 10)], - ), - ]); + notifyListeners(); + } + + Future performCustomSearch() async { + final results = []; + int count = 0; + final dir = Directory(_searchDirectory); + + await for (final entity in dir.list(recursive: true)) { + if (entity is File && _matchesFileType(entity.path, fileType)) { + try { + final lines = await entity.readAsLines(); + for (int i = 0; i < lines.length; i++) { + final line = lines[i].trim(); + //过滤掉2个字符以内的行(如 ); 等) + if (line.length < 3) continue; + + final script = 'match(${jsonEncode(line)});'; + + final result = _jsRuntime.evaluate(script); + if (result.isError) { + Logger().error('JavaScript 执行错误: ${result.stringResult}'); + continue; + } + + if (result.stringResult == 'true') { + if (searchMode == SearchMode.locate) { + results.add( + SearchResult( + filePath: entity.path, + lineNumber: i + 1, + lineContent: line, + matches: [], + queryTerm: "自定义", + ), + ); + } else { + count = count + 1; + } + } + } + } catch (e) { + Logger().error('Error reading file ${entity.path}: $e'); + } + } + } + + if (searchMode == SearchMode.locate) { + Logger().debug("处理结果--定位${results.length.toString()}"); + _results.addAll(results); + } else { + Logger().debug("处理结果--计数${count.toString()}"); + _results.add( + SearchResult( + filePath: "JavaScript", + lineNumber: count, + lineContent: '', + matches: [], + queryTerm: "JavaScript", + ), + ); + } + } + + Future startSearch() async { + _results.clear(); + + // 校验搜索内容 + if (searchQuery.isEmpty) { + Logger().info("搜索内容不能为空"); + return; + } + + if (searchDirectory.isEmpty || !Directory(searchDirectory).existsSync()) { + Logger().info("搜索目录不能为空"); + return; + } + + if (customRule) { + final jsFunction = 'function match(content) {$searchQuery};'; + try { + // 执行 JS 代码进行语法检查 + final result = _jsRuntime.evaluate(jsFunction); + if (result.isError) { + Logger().error('JavaScript 语法错误: ${result.rawResult.toString()}'); + return; + } + + final test = _jsRuntime.evaluate("match('test');"); + if (test.stringResult != 'true' && test.stringResult != 'false') { + Logger().error('自定规则逻辑错误,没有返回布尔值,返回值为: ${test.stringResult}'); + return; + } + + await performCustomSearch(); + // 语法检查通过,进行自定义规则搜索 + } catch (e) { + Logger().error('JavaScript 语法检查错误: $e'); + return; + } finally { + notifyListeners(); + _jsRuntime.dispose(); + } + } else { + try { + if (searchMode == SearchMode.locate) { + _results.addAll( + await ContentSearchService.performLocateSearch( + directory: searchDirectory, + query: searchQuery, + fileType: fileType, + caseSensitive: caseSensitive, + wholeWord: wholeWord, + useRegex: useRegex, + ), + ); + } else { + final counts = await ContentSearchService.performCountSearch( + directory: searchDirectory, + query: searchQuery, + fileType: fileType, + caseSensitive: caseSensitive, + wholeWord: wholeWord, + useRegex: useRegex, + ); + + counts.forEach((keyword, count) { + _results.add( + SearchResult( + filePath: keyword, + lineNumber: count, + lineContent: '', + matches: [], + queryTerm: keyword, + ), + ); + }); + } + } catch (e) { + Logger().error("搜索出错: $e"); + } finally { + notifyListeners(); + } + } } Future pickDirectory() async { @@ -94,27 +235,12 @@ class ContentSearchController with ChangeNotifier { searchDirectory = dir; } } -} -enum SearchMode { locate, count } - -class SearchResult { - final String filePath; - final int lineNumber; - final String lineContent; - final List matches; - - SearchResult({ - required this.filePath, - required this.lineNumber, - required this.lineContent, - required this.matches, - }); + bool _matchesFileType(String filePath, String fileType) { + if (fileType == '*.*') return true; + final ext = path.extension(filePath).toLowerCase(); + return ext == fileType.toLowerCase(); + } } -class MatchResult { - final int start; - final int end; - - const MatchResult({required this.start, required this.end}); -} +enum SearchMode { locate, count } diff --git a/win_text_editor/lib/app/modules/content_search/content_search_service.dart b/win_text_editor/lib/app/modules/content_search/content_search_service.dart new file mode 100644 index 0000000..1a23c2c --- /dev/null +++ b/win_text_editor/lib/app/modules/content_search/content_search_service.dart @@ -0,0 +1,171 @@ +// lib/app/modules/content_search/content_search_service.dart + +import 'dart:io'; +import 'package:path/path.dart' as path; + +class ContentSearchService { + static Future> performLocateSearch({ + required String directory, + required String query, + required String fileType, + required bool caseSensitive, + required bool wholeWord, + required bool useRegex, + }) async { + final results = []; + final dir = Directory(directory); + final queries = _splitQuery(query); // 分割查询字符串 + + for (final q in queries) { + final pattern = _buildSearchPattern( + query: q, + caseSensitive: caseSensitive, + wholeWord: wholeWord, + useRegex: useRegex, + ); + + await for (final entity in dir.list(recursive: true)) { + if (entity is File && _matchesFileType(entity.path, fileType)) { + await _searchInFile(entity, pattern, results, q); // 传递当前查询项 + } + } + } + + return results; + } + + /// 计数搜索(返回每个关键词的匹配数) + static Future> performCountSearch({ + required String directory, + required String query, + required String fileType, + required bool caseSensitive, + required bool wholeWord, + required bool useRegex, + }) async { + final counts = {}; + final dir = Directory(directory); + final queries = _splitQuery(query); // 分割查询字符串 + + for (final q in queries) { + final pattern = _buildSearchPattern( + query: q, + caseSensitive: caseSensitive, + wholeWord: wholeWord, + useRegex: useRegex, + ); + + await for (final entity in dir.list(recursive: true)) { + if (entity is File && _matchesFileType(entity.path, fileType)) { + await _countInFile(entity, pattern, counts, q); // 传递当前查询项 + } + } + } + + return counts; + } + + /// 分割查询字符串(按半角逗号分隔,并去除空格) + static List _splitQuery(String query) { + return query.split(',').map((q) => q.trim()).where((q) => q.isNotEmpty).toList(); + } + + /// 构建正则表达式(原逻辑不变) + static RegExp _buildSearchPattern({ + required String query, + required bool caseSensitive, + required bool wholeWord, + required bool useRegex, + }) { + String pattern; + if (useRegex) { + pattern = query; + } else { + pattern = RegExp.escape(query); + if (wholeWord) { + pattern = '\\b$pattern\\b'; + } + } + return RegExp(pattern, caseSensitive: caseSensitive, multiLine: true); + } + + /// 检查文件类型(原逻辑不变) + static bool _matchesFileType(String filePath, String fileType) { + if (fileType == '*.*') return true; + final ext = path.extension(filePath).toLowerCase(); + return ext == fileType.toLowerCase(); + } + + /// 在文件中搜索匹配项(增加 queryTerm 参数) + static Future _searchInFile( + File file, + RegExp pattern, + List results, + String queryTerm, // 当前查询项 + ) async { + try { + final lines = await file.readAsLines(); + for (int i = 0; i < lines.length; i++) { + final line = lines[i]; + final matches = pattern.allMatches(line); + + if (matches.isNotEmpty) { + results.add( + SearchResult( + filePath: file.path, + lineNumber: i + 1, + lineContent: line, + matches: matches.map((m) => MatchResult(start: m.start, end: m.end)).toList(), + queryTerm: queryTerm, // 记录匹配的查询项 + ), + ); + } + } + } catch (e) { + print('Error reading file ${file.path}: $e'); + } + } + + /// 在文件中计数匹配项(增加 queryTerm 参数) + static Future _countInFile( + File file, + RegExp pattern, + Map counts, + String queryTerm, // 当前查询项 + ) async { + try { + final content = await file.readAsString(); + final matches = pattern.allMatches(content); + + if (matches.isNotEmpty) { + counts[queryTerm] = (counts[queryTerm] ?? 0) + matches.length; + } + } catch (e) { + print('Error reading file ${file.path}: $e'); + } + } +} + +/// 搜索结果类(新增 queryTerm 字段) +class SearchResult { + final String filePath; + final int lineNumber; + final String lineContent; + final List matches; + final String queryTerm; // 记录匹配的查询项 + + SearchResult({ + required this.filePath, + required this.lineNumber, + required this.lineContent, + required this.matches, + required this.queryTerm, + }); +} + +class MatchResult { + final int start; + final int end; + + const MatchResult({required this.start, required this.end}); +} diff --git a/win_text_editor/lib/app/modules/content_search/directory_settings.dart b/win_text_editor/lib/app/modules/content_search/directory_settings.dart index 2d06870..de11d4e 100644 --- a/win_text_editor/lib/app/modules/content_search/directory_settings.dart +++ b/win_text_editor/lib/app/modules/content_search/directory_settings.dart @@ -9,7 +9,7 @@ class DirectorySettings extends StatelessWidget { Widget build(BuildContext context) { final controller = context.watch(); final searchDirectoryController = TextEditingController(text: controller.searchDirectory); - + return Card( child: Padding( padding: const EdgeInsets.all(8.0), @@ -33,7 +33,7 @@ class DirectorySettings extends StatelessWidget { ), const SizedBox(width: 8), IconButton( - icon: const Icon(Icons.folder_open), + icon: const Icon(Icons.folder_open), onPressed: () async { await controller.pickDirectory(); searchDirectoryController.text = controller.searchDirectory; diff --git a/win_text_editor/lib/app/modules/content_search/results_view.dart b/win_text_editor/lib/app/modules/content_search/results_view.dart index 5c7d4d0..2045898 100644 --- a/win_text_editor/lib/app/modules/content_search/results_view.dart +++ b/win_text_editor/lib/app/modules/content_search/results_view.dart @@ -1,6 +1,9 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:syncfusion_flutter_datagrid/datagrid.dart'; +import 'package:path/path.dart' as path; import 'package:win_text_editor/app/modules/content_search/content_search_controller.dart'; +import 'package:win_text_editor/app/modules/content_search/content_search_service.dart'; class ResultsView extends StatelessWidget { const ResultsView({super.key}); @@ -8,84 +11,206 @@ class ResultsView extends StatelessWidget { @override Widget build(BuildContext context) { final controller = context.watch(); - return Card( - child: Column( - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text( - controller.searchMode == SearchMode.locate ? '定位结果' : '计数结果', - style: Theme.of(context).textTheme.titleMedium, - ), + + // 监听搜索模式的变化,当搜索模式改变时,清空结果列表 + final previousSearchMode = context.select( + (c) => c.searchMode, + ); + if (previousSearchMode != controller.searchMode) { + controller.clearResults(); + } + + return Card(child: _buildResultsGrid(controller)); + } + + Widget _buildResultsGrid(ContentSearchController controller) { + return controller.searchMode == SearchMode.locate + ? _buildLocateGrid(controller) + : _buildCountGrid(controller); + } + + Widget _buildLocateGrid(ContentSearchController controller) { + return SfDataGrid( + rowHeight: 40, + source: LocateDataSource(controller), + columns: [ + GridColumn( + columnName: 'file', + width: 300, + label: Container( + alignment: Alignment.center, + color: Colors.grey[200], + child: const Text('文件(行号)', style: TextStyle(fontWeight: FontWeight.bold)), ), - Expanded( - child: - controller.searchMode == SearchMode.locate - ? _buildLocateResults(controller) - : _buildCountResults(controller), + ), + GridColumn( + columnName: 'content', + label: Container( + alignment: Alignment.center, + color: Colors.grey[200], + child: const Text('内容', style: TextStyle(fontWeight: FontWeight.bold)), ), - ], - ), + ), + ], + selectionMode: SelectionMode.multiple, + navigationMode: GridNavigationMode.cell, + allowColumnsResizing: true, + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + allowSorting: false, + allowFiltering: false, + columnWidthMode: ColumnWidthMode.fill, + isScrollbarAlwaysShown: true, ); } - Widget _buildLocateResults(controller) { - return ListView.builder( - itemCount: controller.results.length, - itemBuilder: (ctx, index) { - final result = controller.results[index]; - return ExpansionTile( - title: Text('${result.filePath}:${result.lineNumber}'), - children: [ - Padding( - padding: const EdgeInsets.all(8.0), - child: Text.rich(_buildHighlightedText(result.lineContent, result.matches)), - ), - ], - ); - }, + Widget _buildCountGrid(ContentSearchController controller) { + return SfDataGrid( + rowHeight: 40, + source: CountDataSource(controller), + columns: [ + GridColumn( + columnName: 'keyword', + width: 300, + label: Container( + alignment: Alignment.center, + color: Colors.grey[200], + child: const Text('关键词', style: TextStyle(fontWeight: FontWeight.bold)), + ), + ), + GridColumn( + columnName: 'count', + label: Container( + alignment: Alignment.center, + color: Colors.grey[200], + child: const Text('匹配数量', style: TextStyle(fontWeight: FontWeight.bold)), + ), + ), + ], + selectionMode: SelectionMode.multiple, + navigationMode: GridNavigationMode.cell, + allowColumnsResizing: true, + gridLinesVisibility: GridLinesVisibility.both, + headerGridLinesVisibility: GridLinesVisibility.both, + columnWidthMode: ColumnWidthMode.fill, + isScrollbarAlwaysShown: true, ); } +} - Widget _buildCountResults(controller) { - final counts = {}; - for (var r in controller.results) { - // counts[r.filePath] = (counts[r.filePath] ?? 0) + r.matches.length; - } +class LocateDataSource extends DataGridSource { + final ContentSearchController controller; + + LocateDataSource(this.controller); - return ListView.builder( - itemCount: counts.length, - itemBuilder: (ctx, index) { - final entry = counts.entries.elementAt(index); - return ListTile( - leading: const Icon(Icons.insert_drive_file), - title: Text(entry.key), - trailing: Chip(label: Text('${entry.value}处')), + @override + List get rows => + controller.results.map((result) { + return DataGridRow( + cells: [ + DataGridCell( + columnName: 'file', + value: '${path.basename(result.filePath)}(${result.lineNumber})', + ), + DataGridCell( + columnName: 'content', + value: result, // 传递整个结果对象用于高亮显示 + ), + ], ); - }, + }).toList(); + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + final cells = row.getCells(); + final result = cells[1].value as SearchResult; + + return DataGridRowAdapter( + cells: [ + // 文件名单元格 + Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.all(8.0), + child: Text(cells[0].value.toString(), overflow: TextOverflow.ellipsis, maxLines: 1), + ), + // 内容单元格(带高亮) + Container( + alignment: Alignment.centerLeft, + padding: const EdgeInsets.all(8.0), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: _buildHighlightedText(result.lineContent, result.matches), + ), + ), + ], ); } - TextSpan _buildHighlightedText(String text, List matches) { + Widget _buildHighlightedText(String text, matches) { final spans = []; int lastEnd = 0; for (final match in matches) { if (match.start > lastEnd) { - spans.add(TextSpan(text: text.substring(lastEnd, match.start))); + spans.add( + TextSpan( + text: text.substring(lastEnd, match.start), + style: const TextStyle(color: Colors.black), + ), + ); } spans.add( TextSpan( text: text.substring(match.start, match.end), - style: const TextStyle(backgroundColor: Colors.yellow, fontWeight: FontWeight.bold), + style: const TextStyle(color: Colors.blue, fontWeight: FontWeight.bold), ), ); lastEnd = match.end; } if (lastEnd < text.length) { - spans.add(TextSpan(text: text.substring(lastEnd))); + spans.add( + TextSpan(text: text.substring(lastEnd), style: const TextStyle(color: Colors.black)), + ); + } + + return RichText(text: TextSpan(children: spans), overflow: TextOverflow.clip); + } +} + +class CountDataSource extends DataGridSource { + final ContentSearchController controller; + late final List> _counts; + + CountDataSource(this.controller) { + final counts = {}; + for (var result in controller.results) { + counts[result.filePath] = (counts[result.filePath] ?? 0) + result.lineNumber; } + _counts = counts.entries.toList(); + } - return TextSpan(children: spans); + @override + List get rows => + _counts.map((entry) { + return DataGridRow( + cells: [ + DataGridCell(columnName: 'keyword', value: entry.key), + DataGridCell(columnName: 'count', value: '${entry.value}'), + ], + ); + }).toList(); + + @override + DataGridRowAdapter? buildRow(DataGridRow row) { + return DataGridRowAdapter( + cells: + row.getCells().map((cell) { + return Container( + alignment: cell.columnName == 'count' ? Alignment.centerRight : Alignment.centerLeft, + padding: const EdgeInsets.all(8.0), + child: Text(cell.value.toString(), overflow: TextOverflow.ellipsis, maxLines: 1), + ); + }).toList(), + ); } } diff --git a/win_text_editor/lib/app/modules/content_search/search_settings.dart b/win_text_editor/lib/app/modules/content_search/search_settings.dart index f777dc7..7799da1 100644 --- a/win_text_editor/lib/app/modules/content_search/search_settings.dart +++ b/win_text_editor/lib/app/modules/content_search/search_settings.dart @@ -12,6 +12,10 @@ class SearchSettings extends StatelessWidget { Widget build(BuildContext context) { final controller = context.watch(); + WidgetsBinding.instance.addPostFrameCallback((_) { + _searchEditorKey.currentState?.setContent(controller.searchQuery); + }); + return Card( child: Padding( padding: const EdgeInsets.all(8.0), @@ -53,7 +57,12 @@ class SearchSettings extends StatelessWidget { Radio( value: SearchMode.locate, groupValue: controller.searchMode, - onChanged: (value) => controller.searchMode = value!, + onChanged: (value) { + if (value != null) { + controller.clearResults(); // 清除搜索结果 + controller.searchMode = value; + } + }, ), const Text('定位', style: TextStyle(fontSize: 12)), ], @@ -65,7 +74,12 @@ class SearchSettings extends StatelessWidget { Radio( value: SearchMode.count, groupValue: controller.searchMode, - onChanged: (value) => controller.searchMode = value!, + onChanged: (value) { + if (value != null) { + controller.clearResults(); // 清除搜索结果 + controller.searchMode = value; + } + }, ), const Text('计数', style: TextStyle(fontSize: 12)), ], @@ -93,6 +107,7 @@ class SearchSettings extends StatelessWidget { : (value) { controller.caseSensitive = value!; controller.customRule = false; + controller.useRegex = false; }, activeColor: controller.customRule ? Colors.grey : null, ), @@ -110,6 +125,7 @@ class SearchSettings extends StatelessWidget { : (value) { controller.wholeWord = value!; controller.customRule = false; + controller.useRegex = false; }, activeColor: controller.customRule ? Colors.grey : null, ), @@ -130,6 +146,8 @@ class SearchSettings extends StatelessWidget { controller.customRule ? null : (value) { + controller.caseSensitive = false; + controller.wholeWord = false; controller.useRegex = value!; controller.customRule = false; }, @@ -166,7 +184,7 @@ class SearchSettings extends StatelessWidget { text: "在搜索内容输入框中输入js函数体:\n" "function boolean match(content) {//content为单行文本\n" - "}//返回true或者false", + "}//返回是否匹配", style: TextStyle(fontSize: 12, fontFamily: 'monospace'), ), ), diff --git a/win_text_editor/pubspec.lock b/win_text_editor/pubspec.lock index a3f00b1..ae831e7 100644 --- a/win_text_editor/pubspec.lock +++ b/win_text_editor/pubspec.lock @@ -126,6 +126,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_js: + dependency: "direct main" + description: + name: flutter_js + sha256: "0d22d73a474b5b80c3ab5508e7c3eab6fb20beea9dec45bbd21088cfd27a5e61" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.8.3" flutter_lints: dependency: "direct dev" description: @@ -160,6 +168,22 @@ packages: description: flutter source: sdk version: "0.0.0" + http: + dependency: transitive + description: + name: http + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.0" + http_parser: + dependency: transitive + description: + name: http_parser + sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + url: "https://pub.flutter-io.cn" + source: hosted + version: "4.1.2" leak_tracker: dependency: transitive description: @@ -225,7 +249,7 @@ packages: source: hosted version: "1.0.0" path: - dependency: transitive + dependency: "direct main" description: name: path sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" @@ -349,6 +373,30 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "1.4.1" + sync_http: + dependency: transitive + description: + name: sync_http + sha256: "7f0cd72eca000d2e026bcd6f990b81d0ca06022ef4e32fb257b30d3d1014a961" + url: "https://pub.flutter-io.cn" + source: hosted + version: "0.3.1" + syncfusion_flutter_core: + dependency: transitive + description: + name: syncfusion_flutter_core + sha256: "9f0a4593f7642b2f106e329734d0e5fc746baf8d0a59495eec586cd0d9ba7d02" + url: "https://pub.flutter-io.cn" + source: hosted + version: "22.2.12" + syncfusion_flutter_datagrid: + dependency: "direct main" + description: + name: syncfusion_flutter_datagrid + sha256: ae93228333ebed39bc59c90bc40cfd3d5a0361591a330fe551b355d3a49a265c + url: "https://pub.flutter-io.cn" + source: hosted + version: "22.2.12" term_glyph: dependency: transitive description: @@ -365,6 +413,14 @@ packages: url: "https://pub.flutter-io.cn" source: hosted version: "0.7.4" + typed_data: + dependency: transitive + description: + name: typed_data + sha256: f9049c039ebfeb4cf7a7104a675823cd72dba8297f264b6637062516699fa006 + url: "https://pub.flutter-io.cn" + source: hosted + version: "1.4.0" vector_math: dependency: transitive description: diff --git a/win_text_editor/pubspec.yaml b/win_text_editor/pubspec.yaml index 9f92ed6..93e68a1 100644 --- a/win_text_editor/pubspec.yaml +++ b/win_text_editor/pubspec.yaml @@ -17,6 +17,9 @@ dependencies: flutter_syntax_view: ^4.1.7 expandable: ^5.0.1 collection: ^1.17.0 + path: ^1.8.0 + syncfusion_flutter_datagrid: ^22.1.40 + flutter_js: ^0.8.3 dev_dependencies: flutter_test: diff --git a/win_text_editor/windows/flutter/generated_plugin_registrant.cc b/win_text_editor/windows/flutter/generated_plugin_registrant.cc index a38b023..760476a 100644 --- a/win_text_editor/windows/flutter/generated_plugin_registrant.cc +++ b/win_text_editor/windows/flutter/generated_plugin_registrant.cc @@ -7,12 +7,15 @@ #include "generated_plugin_registrant.h" #include +#include #include #include void RegisterPlugins(flutter::PluginRegistry* registry) { BitsdojoWindowPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("BitsdojoWindowPlugin")); + FlutterJsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("FlutterJsPlugin")); ScreenRetrieverPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverPlugin")); WindowManagerPluginRegisterWithRegistrar( diff --git a/win_text_editor/windows/flutter/generated_plugins.cmake b/win_text_editor/windows/flutter/generated_plugins.cmake index b404ce5..08bf885 100644 --- a/win_text_editor/windows/flutter/generated_plugins.cmake +++ b/win_text_editor/windows/flutter/generated_plugins.cmake @@ -4,6 +4,7 @@ list(APPEND FLUTTER_PLUGIN_LIST bitsdojo_window_windows + flutter_js screen_retriever window_manager )