From 3085f42aa5999eff43f3d81895c00c4b7cdb9f1f Mon Sep 17 00:00:00 2001 From: hejl Date: Sun, 11 May 2025 10:34:02 +0800 Subject: [PATCH] =?UTF-8?q?=E6=89=93=E5=BC=80=E6=96=87=E4=BB=B6OK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- win_text_editor/lib/app/widgets/text_tab.dart | 102 ++++++++++++++---- 1 file changed, 83 insertions(+), 19 deletions(-) diff --git a/win_text_editor/lib/app/widgets/text_tab.dart b/win_text_editor/lib/app/widgets/text_tab.dart index 775be47..7f38829 100644 --- a/win_text_editor/lib/app/widgets/text_tab.dart +++ b/win_text_editor/lib/app/widgets/text_tab.dart @@ -2,17 +2,51 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.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 StatelessWidget { +class TextTab extends StatefulWidget { final String tabId; const TextTab({super.key, required this.tabId}); @override - Widget build(BuildContext context) { - final provider = Provider.of(context); - final tab = provider.tabs.firstWhere((t) => t.id == tabId); + State createState() => _TextTabState(); +} + +class _TextTabState extends State { + late TextEditingController _controller; + late EditorProvider _provider; + + @override + void initState() { + super.initState(); + _provider = Provider.of(context, listen: false); + _controller = TextEditingController(text: _getCurrentContent()); + } + + String _getCurrentContent() { + return _provider.tabs.firstWhere((t) => t.id == widget.tabId).content; + } + + @override + void didUpdateWidget(TextTab oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.tabId != widget.tabId) { + _controller.text = _getCurrentContent(); + } + } + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + @override + Widget build(BuildContext context) { + final tab = _provider.tabs.firstWhere((t) => t.id == widget.tabId); // Add this line + return Column( children: [ // 新增工具条 @@ -26,23 +60,27 @@ class TextTab extends StatelessWidget { child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - const Text('源文本', style: TextStyle(fontWeight: FontWeight.bold)), + Text( + '源文本${tab.content.isEmpty ? '' : ' (${tab.content.length}字符)'}', + style: const TextStyle(fontWeight: FontWeight.bold), + ), Row( children: [ IconButton( icon: const Icon(Icons.folder_open, size: 20), tooltip: '打开文件', - onPressed: () => _openFile(context, tabId), + onPressed: () => _openFile(context), ), IconButton( icon: const Icon(Icons.content_copy, size: 20), tooltip: '复制内容', - onPressed: () => _copyToClipboard(context, tab.content), + onPressed: + tab.content.isEmpty ? null : () => _copyToClipboard(context, tab.content), ), IconButton( icon: const Icon(Icons.save, size: 20), - tooltip: '保存文件', - onPressed: () => _saveFile(context, tab.content), + tooltip: '保存到文件', + onPressed: tab.content.isEmpty ? null : () => _saveFile(context, tab.content), ), ], ), @@ -52,12 +90,11 @@ class TextTab extends StatelessWidget { // 文本编辑区 Expanded( child: TextField( + controller: _controller, maxLines: null, - controller: TextEditingController(text: tab.content), - onChanged: (text) => provider.updateContent(tabId, text), + onChanged: (text) => _provider.updateContent(widget.tabId, text), decoration: const InputDecoration( border: InputBorder.none, - hintText: '开始输入内容...', contentPadding: EdgeInsets.all(16), ), ), @@ -66,14 +103,41 @@ class TextTab extends StatelessWidget { ); } - // 打开文件模拟功能 - Future _openFile(BuildContext context, String tabId) async { - final provider = Provider.of(context, listen: false); - // 这里是模拟代码,实际应该使用文件选择器 - const mockContent = "从文件加载的示例文本..."; - provider.updateContent(tabId, mockContent); + // _openFile方法现在需要更新控制器 + Future _openFile(BuildContext context) async { + try { + 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(); - ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('已加载文件内容'))); + // 同时更新Provider和控制器 + _provider.updateContent(widget.tabId, content); + setState(() { + _controller.text = content; + }); + + // 强制刷新文本控制器 + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('已加载: ${file.path}'))); + } + } + } on FormatException { + // 二进制文件错误 + ScaffoldMessenger.of(context).showSnackBar(const SnackBar(content: Text('这不是可读的文本文件'))); + } on FileSystemException catch (e) { + // 文件系统错误 + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('文件访问错误: ${e.message}'))); + } catch (e) { + if (context.mounted) { + ScaffoldMessenger.of( + context, + ).showSnackBar(SnackBar(content: Text('读取失败: ${e.toString()}'))); + } + } } // 复制到剪贴板