Browse Source

增加js自定义规则搜索

master
hejl 2 months ago
parent
commit
e660d0de22
  1. 25
      win_text_editor/.vscode/launch.json
  2. 4
      win_text_editor/lib/app/components/text_editor.dart
  3. 202
      win_text_editor/lib/app/modules/content_search/content_search_controller.dart
  4. 171
      win_text_editor/lib/app/modules/content_search/content_search_service.dart
  5. 4
      win_text_editor/lib/app/modules/content_search/directory_settings.dart
  6. 225
      win_text_editor/lib/app/modules/content_search/results_view.dart
  7. 24
      win_text_editor/lib/app/modules/content_search/search_settings.dart
  8. 58
      win_text_editor/pubspec.lock
  9. 3
      win_text_editor/pubspec.yaml
  10. 3
      win_text_editor/windows/flutter/generated_plugin_registrant.cc
  11. 1
      win_text_editor/windows/flutter/generated_plugins.cmake

25
win_text_editor/.vscode/launch.json vendored

@ -0,0 +1,25 @@ @@ -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"
}
]
}

4
win_text_editor/lib/app/components/text_editor.dart

@ -151,4 +151,8 @@ class TextEditorState extends State<TextEditor> { @@ -151,4 +151,8 @@ class TextEditorState extends State<TextEditor> {
),
);
}
void setContent(String content) {
_editorController.updateContent(content);
}
}

202
win_text_editor/lib/app/modules/content_search/content_search_controller.dart

@ -1,6 +1,15 @@ @@ -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 { @@ -14,8 +23,11 @@ class ContentSearchController with ChangeNotifier {
bool _customRule = false;
SearchMode _searchMode = SearchMode.locate;
final List<SearchResult> _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 { @@ -69,23 +81,152 @@ class ContentSearchController with ChangeNotifier {
notifyListeners();
}
Future<void> 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<void> performCustomSearch() async {
final results = <SearchResult>[];
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<void> 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<void> pickDirectory() async {
@ -94,27 +235,12 @@ class ContentSearchController with ChangeNotifier { @@ -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<MatchResult> 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 }

171
win_text_editor/lib/app/modules/content_search/content_search_service.dart

@ -0,0 +1,171 @@ @@ -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<List<SearchResult>> performLocateSearch({
required String directory,
required String query,
required String fileType,
required bool caseSensitive,
required bool wholeWord,
required bool useRegex,
}) async {
final results = <SearchResult>[];
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<Map<String, int>> performCountSearch({
required String directory,
required String query,
required String fileType,
required bool caseSensitive,
required bool wholeWord,
required bool useRegex,
}) async {
final counts = <String, int>{};
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<String> _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<void> _searchInFile(
File file,
RegExp pattern,
List<SearchResult> 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<void> _countInFile(
File file,
RegExp pattern,
Map<String, int> 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<MatchResult> 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});
}

4
win_text_editor/lib/app/modules/content_search/directory_settings.dart

@ -9,7 +9,7 @@ class DirectorySettings extends StatelessWidget { @@ -9,7 +9,7 @@ class DirectorySettings extends StatelessWidget {
Widget build(BuildContext context) {
final controller = context.watch<ContentSearchController>();
final searchDirectoryController = TextEditingController(text: controller.searchDirectory);
return Card(
child: Padding(
padding: const EdgeInsets.all(8.0),
@ -33,7 +33,7 @@ class DirectorySettings extends StatelessWidget { @@ -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;

225
win_text_editor/lib/app/modules/content_search/results_view.dart

@ -1,6 +1,9 @@ @@ -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 { @@ -8,84 +11,206 @@ class ResultsView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final controller = context.watch<ContentSearchController>();
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<ContentSearchController, SearchMode>(
(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 = <String, int>{};
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<DataGridRow> 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<MatchResult> matches) {
Widget _buildHighlightedText(String text, matches) {
final spans = <TextSpan>[];
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<MapEntry<String, int>> _counts;
CountDataSource(this.controller) {
final counts = <String, int>{};
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<DataGridRow> 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(),
);
}
}

24
win_text_editor/lib/app/modules/content_search/search_settings.dart

@ -12,6 +12,10 @@ class SearchSettings extends StatelessWidget { @@ -12,6 +12,10 @@ class SearchSettings extends StatelessWidget {
Widget build(BuildContext context) {
final controller = context.watch<ContentSearchController>();
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 { @@ -53,7 +57,12 @@ class SearchSettings extends StatelessWidget {
Radio<SearchMode>(
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 { @@ -65,7 +74,12 @@ class SearchSettings extends StatelessWidget {
Radio<SearchMode>(
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 { @@ -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 { @@ -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 { @@ -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 { @@ -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'),
),
),

58
win_text_editor/pubspec.lock

@ -126,6 +126,14 @@ packages: @@ -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: @@ -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: @@ -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: @@ -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: @@ -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:

3
win_text_editor/pubspec.yaml

@ -17,6 +17,9 @@ dependencies: @@ -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:

3
win_text_editor/windows/flutter/generated_plugin_registrant.cc

@ -7,12 +7,15 @@ @@ -7,12 +7,15 @@
#include "generated_plugin_registrant.h"
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
#include <flutter_js/flutter_js_plugin.h>
#include <screen_retriever/screen_retriever_plugin.h>
#include <window_manager/window_manager_plugin.h>
void RegisterPlugins(flutter::PluginRegistry* registry) {
BitsdojoWindowPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
FlutterJsPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("FlutterJsPlugin"));
ScreenRetrieverPluginRegisterWithRegistrar(
registry->GetRegistrarForPlugin("ScreenRetrieverPlugin"));
WindowManagerPluginRegisterWithRegistrar(

1
win_text_editor/windows/flutter/generated_plugins.cmake

@ -4,6 +4,7 @@ @@ -4,6 +4,7 @@
list(APPEND FLUTTER_PLUGIN_LIST
bitsdojo_window_windows
flutter_js
screen_retriever
window_manager
)

Loading…
Cancel
Save