Browse Source

能够加载小于10M的文件了

master
hejl 2 months ago
parent
commit
b06ecf4811
  1. 2
      win_text_editor/lib/app/providers/editor_provider.dart
  2. 87
      win_text_editor/lib/app/widgets/text_tab.dart

2
win_text_editor/lib/app/providers/editor_provider.dart

@ -51,7 +51,7 @@ class EditorProvider with ChangeNotifier { @@ -51,7 +51,7 @@ class EditorProvider with ChangeNotifier {
if (name != null) {
tab.fileName = name;
}
Logger().debug("内容更新成功,文件:${tab.fileName}, ${tab.content.length}");
// Logger().debug("内容更新成功,文件:${tab.fileName}, ${tab.content.length}");
notifyListeners();
} catch (e) {
Logger().error("更新内容失败: ${e.toString()}", source: 'EditorProvider');

87
win_text_editor/lib/app/widgets/text_tab.dart

@ -1,11 +1,11 @@ @@ -1,11 +1,11 @@
import 'dart:convert';
import 'dart:ui';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
import 'package:flutter/services.dart'; //
import 'package:flutter/services.dart';
import 'package:win_text_editor/app/providers/editor_provider.dart';
import 'package:file_picker/file_picker.dart';
import 'dart:io';
class TextTab extends StatefulWidget {
final String tabId;
@ -21,8 +21,9 @@ class _TextTabState extends State<TextTab> { @@ -21,8 +21,9 @@ class _TextTabState extends State<TextTab> {
late EditorProvider _provider;
late FocusNode _focusNode;
late ScrollController _scrollController;
bool _isLoading = false;
static const int maxFileSize = 10 * 1024 * 1024; // 10MB
@override
@override
void initState() {
super.initState();
@ -51,7 +52,7 @@ class _TextTabState extends State<TextTab> { @@ -51,7 +52,7 @@ class _TextTabState extends State<TextTab> {
void dispose() {
_controller.dispose();
_focusNode.dispose();
_scrollController.dispose(); //
_scrollController.dispose();
super.dispose();
}
@ -80,7 +81,7 @@ class _TextTabState extends State<TextTab> { @@ -80,7 +81,7 @@ class _TextTabState extends State<TextTab> {
IconButton(
icon: const Icon(Icons.folder_open, size: 20),
tooltip: '打开文件',
onPressed: () => _openFile(context),
onPressed: _isLoading ? null : () => _openFile(context),
),
IconButton(
icon: const Icon(Icons.content_copy, size: 20),
@ -93,6 +94,15 @@ class _TextTabState extends State<TextTab> { @@ -93,6 +94,15 @@ class _TextTabState extends State<TextTab> {
tooltip: '保存到文件',
onPressed: tab.content.isEmpty ? null : () => _saveFile(context, tab.content),
),
if (_isLoading)
const Padding(
padding: EdgeInsets.only(left: 8),
child: SizedBox(
width: 16,
height: 16,
child: CircularProgressIndicator(strokeWidth: 2),
),
),
],
),
],
@ -105,10 +115,9 @@ class _TextTabState extends State<TextTab> { @@ -105,10 +115,9 @@ class _TextTabState extends State<TextTab> {
dragDevices: {PointerDeviceKind.touch, PointerDeviceKind.mouse},
),
child: SingleChildScrollView(
controller: _scrollController, //
controller: _scrollController,
child: Stack(
children: [
// TextField
TextField(
controller: _controller,
focusNode: _focusNode,
@ -121,7 +130,7 @@ class _TextTabState extends State<TextTab> { @@ -121,7 +130,7 @@ class _TextTabState extends State<TextTab> {
style: TextStyle(
fontFamily: 'monospace',
fontSize: 14,
color: Theme.of(context).textTheme.bodyLarge?.color, // 使
color: Theme.of(context).textTheme.bodyLarge?.color,
),
),
],
@ -135,34 +144,74 @@ class _TextTabState extends State<TextTab> { @@ -135,34 +144,74 @@ class _TextTabState extends State<TextTab> {
Future<void> _openFile(BuildContext context) async {
try {
setState(() => _isLoading = true);
final result = await FilePicker.platform.pickFiles(type: FileType.any, allowMultiple: false);
if (result != null && result.files.single.path != null) {
final file = File(result.files.single.path!);
final content = await file.readAsString();
final fileSize = await file.length();
//
if (fileSize > maxFileSize) {
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(const SnackBar(content: Text('文件过大(超过10MB),无法处理')));
}
return;
}
//
_provider.updateContent(widget.tabId, '', result.files.first.name);
_controller.text = '';
//
final stream = file.openRead();
final lines = stream.transform(utf8.decoder).transform(const LineSplitter());
// provider和控制器
_provider.updateContent(widget.tabId, content, result.files.first.name);
_controller.text = content; //
await for (final line in lines) {
if (!mounted) break; //
setState(() {
_controller.text += '$line\n';
_provider.updateContent(widget.tabId, _controller.text, result.files.first.name);
});
//
WidgetsBinding.instance.addPostFrameCallback((_) {
_scrollController.jumpTo(_scrollController.position.maxScrollExtent);
});
//
await Future.delayed(const Duration(milliseconds: 10));
}
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已加载: ${file.path}')));
}
}
} on FormatException {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这不是可读的文本文件')));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这不是可读的文本文件')));
}
} on FileSystemException catch (e) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('文件访问错误: ${e.message}')));
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('文件访问错误: ${e.message}')));
}
} catch (e) {
if (context.mounted) {
ScaffoldMessenger.of(
context,
).showSnackBar(SnackBar(content: Text('读取失败: ${e.toString()}')));
}
} finally {
if (mounted) {
setState(() => _isLoading = false);
}
}
}
//
Future<void> _copyToClipboard(BuildContext context, String content) async {
await Clipboard.setData(ClipboardData(text: content));
if (context.mounted) {
@ -170,11 +219,8 @@ class _TextTabState extends State<TextTab> { @@ -170,11 +219,8 @@ class _TextTabState extends State<TextTab> {
}
}
//
//
Future<void> _saveFile(BuildContext context, String content) async {
try {
//
String? outputPath = await FilePicker.platform.saveFile(
dialogTitle: '保存文件',
fileName: 'untitled.txt',
@ -186,9 +232,7 @@ class _TextTabState extends State<TextTab> { @@ -186,9 +232,7 @@ class _TextTabState extends State<TextTab> {
final file = File(outputPath);
//
if (await file.exists()) {
//
final shouldOverwrite = await showDialog<bool>(
context: context,
builder:
@ -211,7 +255,6 @@ class _TextTabState extends State<TextTab> { @@ -211,7 +255,6 @@ class _TextTabState extends State<TextTab> {
if (shouldOverwrite != true) return;
}
//
await file.writeAsString(content);
if (context.mounted) {

Loading…
Cancel
Save