import 'dart:io'; import 'package:flutter/material.dart'; import 'package:file_picker/file_picker.dart'; import 'package:path_provider/path_provider.dart'; import 'package:win_text_editor/app/models/file_node.dart'; import 'package:win_text_editor/app/providers/logger.dart'; import 'package:win_text_editor/app/services/file_service.dart'; class FileProvider with ChangeNotifier { List _fileNodes = []; bool _isLoading = false; String _searchQuery = ''; String? _currentRootPath; // 跟踪当前根路径 bool get isLoading => _isLoading; bool get hasRoot => _fileNodes.isNotEmpty && _fileNodes[0].isRoot; // 移除构造函数的_initFileTree调用 FileProvider(); // 新增方法:手动设置根路径 Future setRootPath(String path) async { _currentRootPath = path; await _loadRootDirectory(); } List get fileNodes => _searchQuery.isEmpty ? _fileNodes : _fileNodes.where((node) => _filterNode(node)).toList(); bool _filterNode(FileNode node) { if (node.name.toLowerCase().contains(_searchQuery.toLowerCase())) { return true; } return node.children.any(_filterNode); } void searchFiles(String query) { _searchQuery = query; notifyListeners(); } void toggleExpand(FileNode node) { node.isExpanded = !node.isExpanded; notifyListeners(); } Future pickAndOpenFile() async { final result = await FilePicker.platform.pickFiles(); if (result != null && result.files.single.path != null) { // 这里需要与编辑器提供者交互来打开文件 Logger().info('File selected: ${result.files.single.path}'); } } Future loadDirectory(String path) async { _isLoading = true; notifyListeners(); try { final directory = Directory(path); final rootNode = FileNode( name: directory.path.split(Platform.pathSeparator).last, path: directory.path, isDirectory: true, isRoot: true, // 添加根节点标识 children: await FileService.buildFileTree(directory.path), ); _fileNodes = [rootNode]; // 将根节点作为唯一顶层节点 } catch (e) { Logger().error('Error loading directory: $e'); _fileNodes = []; } _isLoading = false; notifyListeners(); } Future _loadRootDirectory() async { if (_currentRootPath == null) return; _isLoading = true; notifyListeners(); try { _fileNodes = [ FileNode( name: _currentRootPath!.split(Platform.pathSeparator).last, path: _currentRootPath!, isDirectory: true, isRoot: true, depth: 0, // 根节点深度为0 children: [], // 初始为空,不加载内容 ), ]; } catch (e) { Logger().error('Error loading root directory: $e'); _fileNodes = []; } _isLoading = false; notifyListeners(); } Future loadRootDirectory(String path) async { _isLoading = true; notifyListeners(); try { _fileNodes = [ FileNode( name: path.split(Platform.pathSeparator).last, path: path, isDirectory: true, isRoot: true, children: [], // 初始为空 ), ]; } catch (e) { Logger().error('Error loading root: $e'); _fileNodes = []; } _isLoading = false; notifyListeners(); } Future toggleDirectory(FileNode dirNode) async { if (dirNode.children.isEmpty) { // 首次点击:加载内容 _isLoading = true; notifyListeners(); try { dirNode.children = await FileService.listDirectory(dirNode.path); dirNode.isExpanded = true; } catch (e) { Logger().error('Error loading directory: $e'); dirNode.children = []; } _isLoading = false; notifyListeners(); } else { // 已加载过:只切换展开状态 dirNode.isExpanded = !dirNode.isExpanded; notifyListeners(); } } Future loadDirectoryContents(FileNode dirNode) async { if (dirNode.children.isNotEmpty && dirNode.isExpanded) { // 如果已经加载过且是展开状态,只切换展开状态 dirNode.isExpanded = !dirNode.isExpanded; notifyListeners(); return; } _isLoading = true; notifyListeners(); try { final contents = await FileService.listDirectory( dirNode.path, parentDepth: dirNode.depth, // 确保传递父节点深度 ); final updatedNode = dirNode.copyWith( children: contents, isExpanded: true, // 不需要设置 depth,因为 copyWith 会自动保留原值 ); _replaceNodeInTree(dirNode, updatedNode); } catch (e) { Logger().error('Error loading directory contents: $e'); final updatedNode = dirNode.copyWith(children: []); _replaceNodeInTree(dirNode, updatedNode); } _isLoading = false; notifyListeners(); } void _replaceNodeInTree(FileNode oldNode, FileNode newNode) { for (int i = 0; i < _fileNodes.length; i++) { if (_fileNodes[i] == oldNode) { _fileNodes[i] = newNode; return; } _replaceNodeInChildren(_fileNodes[i], oldNode, newNode); } } void _replaceNodeInChildren(FileNode parent, FileNode oldNode, FileNode newNode) { for (int i = 0; i < parent.children.length; i++) { if (parent.children[i] == oldNode) { parent.children[i] = newNode; return; } _replaceNodeInChildren(parent.children[i], oldNode, newNode); } } Future refreshFileTree({bool loadContent = false}) async { _isLoading = true; notifyListeners(); try { final rootDir = await getApplicationDocumentsDirectory(); _fileNodes = [ FileNode( name: rootDir.path.split(Platform.pathSeparator).last, path: rootDir.path, isDirectory: true, isRoot: true, // 初始不加载内容 children: loadContent ? await FileService.listDirectory(rootDir.path) : [], ), ]; } catch (e) { Logger().error('Error refreshing file tree: $e'); _fileNodes = []; } _isLoading = false; notifyListeners(); } }