Browse Source

修复中文输入的问题

master
hejl 2 months ago
parent
commit
f8a7081149
  1. 33
      win_text_editor/lib/app/components/text_editor.dart
  2. 103
      win_text_editor/lib/app/modules/content_search/content_search_service.dart

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

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
@ -29,6 +30,8 @@ class TextEditorState extends State<TextEditor> with AutomaticKeepAliveClientMix
final TextEditingController _textController = TextEditingController(); final TextEditingController _textController = TextEditingController();
final FocusNode _focusNode = FocusNode(); final FocusNode _focusNode = FocusNode();
bool _isLoading = false; bool _isLoading = false;
String _lastSyncedText = '';
Timer? _debounceTimer;
@override @override
bool get wantKeepAlive => true; bool get wantKeepAlive => true;
@ -36,26 +39,38 @@ class TextEditorState extends State<TextEditor> with AutomaticKeepAliveClientMix
@override @override
void initState() { void initState() {
super.initState(); super.initState();
_textController.text = widget.initialContent ?? ''; _lastSyncedText = widget.initialContent ?? '';
_textController.text = _lastSyncedText;
_textController.addListener(_handleTextChanged); _textController.addListener(_handleTextChanged);
} }
@override void _handleTextChanged() {
void didUpdateWidget(TextEditor oldWidget) { if (_debounceTimer?.isActive ?? false) {
super.didUpdateWidget(oldWidget); _debounceTimer?.cancel();
if (oldWidget.initialContent != widget.initialContent) {
_textController.text = widget.initialContent ?? '';
} }
_debounceTimer = Timer(const Duration(milliseconds: 300), () {
final currentText = _textController.text;
if (widget.onContentChanged != null && currentText != _lastSyncedText) {
_lastSyncedText = currentText;
widget.onContentChanged!(currentText);
}
});
} }
void _handleTextChanged() { @override
if (widget.onContentChanged != null) { void didUpdateWidget(TextEditor oldWidget) {
widget.onContentChanged!(_textController.text); super.didUpdateWidget(oldWidget);
final newText = widget.initialContent ?? '';
if (newText != _textController.text && newText != _lastSyncedText) {
_lastSyncedText = newText;
_textController.text = newText;
} }
} }
@override @override
void dispose() { void dispose() {
_debounceTimer?.cancel();
_textController.removeListener(_handleTextChanged); _textController.removeListener(_handleTextChanged);
_textController.dispose(); _textController.dispose();
_focusNode.dispose(); _focusNode.dispose();

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

@ -17,19 +17,19 @@ class ContentSearchService {
final queries = _splitQuery(query); // final queries = _splitQuery(query); //
for (final q in queries) { for (final q in queries) {
final pattern = _buildSearchPattern( final pattern = _buildSearchPattern(
query: q, query: q,
caseSensitive: caseSensitive, caseSensitive: caseSensitive,
wholeWord: wholeWord, wholeWord: wholeWord,
useRegex: useRegex, useRegex: useRegex,
); );
await for (final entity in dir.list(recursive: true)) { await for (final entity in dir.list(recursive: true)) {
if (entity is File && _matchesFileType(entity.path, fileType)) { if (entity is File && _matchesFileType(entity.path, fileType)) {
await _searchInFile(entity, pattern, results, q); // await _searchInFile(entity, pattern, results, q); //
}
} }
} }
}
return results; return results;
} }
@ -48,19 +48,19 @@ class ContentSearchService {
final queries = _splitQuery(query); // final queries = _splitQuery(query); //
for (final q in queries) { for (final q in queries) {
final pattern = _buildSearchPattern( final pattern = _buildSearchPattern(
query: q, query: q,
caseSensitive: caseSensitive, caseSensitive: caseSensitive,
wholeWord: wholeWord, wholeWord: wholeWord,
useRegex: useRegex, useRegex: useRegex,
); );
await for (final entity in dir.list(recursive: true)) { await for (final entity in dir.list(recursive: true)) {
if (entity is File && _matchesFileType(entity.path, fileType)) { if (entity is File && _matchesFileType(entity.path, fileType)) {
await _countInFile(entity, pattern, counts, q); // await _countInFile(entity, pattern, counts, q); //
}
} }
} }
}
return counts; return counts;
} }
@ -89,11 +89,76 @@ class ContentSearchService {
return RegExp(pattern, caseSensitive: caseSensitive, multiLine: true); return RegExp(pattern, caseSensitive: caseSensitive, multiLine: true);
} }
///
static bool _matchesFileType(String filePath, String fileType) { static bool _matchesFileType(String filePath, String fileType) {
//
if (fileType == '*.*') return true; if (fileType == '*.*') return true;
final ext = path.extension(filePath).toLowerCase(); if (fileType == '*') return true;
return ext == fileType.toLowerCase();
//
final parts = fileType.split('.');
final patternName = parts.length > 0 ? parts[0] : '';
final patternExt = parts.length > 1 ? parts.sublist(1).join('.') : '';
//
final fileName = path.basename(filePath);
final fileExt = path.extension(fileName).toLowerCase().replaceFirst('.', '');
//
bool nameMatches = true;
if (patternName.isNotEmpty && patternName != '*') {
nameMatches = _matchesWildcard(fileName, patternName);
}
//
bool extMatches = true;
if (patternExt.isNotEmpty) {
if (patternExt == '*') {
extMatches = true;
} else {
extMatches = _matchesWildcard(fileExt, patternExt);
}
}
return nameMatches && extMatches;
}
//
static bool _matchesWildcard(String input, String pattern) {
//
if (pattern == '*') return true;
//
final m = input.length;
final n = pattern.length;
final dp = List.generate(m + 1, (_) => List.filled(n + 1, false));
//
dp[0][0] = true;
// *
for (int j = 1; j <= n; j++) {
if (pattern[j - 1] == '*') {
dp[0][j] = dp[0][j - 1];
}
}
//
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (pattern[j - 1] == '*') {
// *
dp[i][j] = dp[i][j - 1] || dp[i - 1][j];
} else if (pattern[j - 1] == '?' || input[i - 1] == pattern[j - 1]) {
// ?
dp[i][j] = dp[i - 1][j - 1];
} else {
//
dp[i][j] = false;
}
}
}
return dp[m][n];
} }
/// queryTerm /// queryTerm

Loading…
Cancel
Save