diff --git a/win_text_editor/lib/framework/controllers/tab_manager.dart b/win_text_editor/lib/framework/controllers/tab_manager.dart index f78aff1..b23af4a 100644 --- a/win_text_editor/lib/framework/controllers/tab_manager.dart +++ b/win_text_editor/lib/framework/controllers/tab_manager.dart @@ -5,6 +5,7 @@ import 'package:win_text_editor/framework/controllers/logger.dart'; class TabManager with ChangeNotifier { final List _tabs = []; + final Map _tabControllers = {}; // 保存各Tab的Controller String? _activeTabId; List get tabs => _tabs; @@ -28,11 +29,15 @@ class TabManager with ChangeNotifier { String? type, IconData? icon, String content = '', + ChangeNotifier? controller, }) async { final newTab = AppTab(id: id, title: title, type: type, icon: icon, content: content); _tabs.add(newTab); - _activeTabId = newTab.id; + if (controller != null) { + _tabControllers[id] = controller; + } + _activeTabId = id; notifyListeners(); } @@ -47,13 +52,30 @@ class TabManager with ChangeNotifier { void closeTab(String tabId) { Logger().info('关闭选项卡: $tabId'); - _tabs.removeWhere((tab) => tab.id == tabId); + final controller = _tabControllers[tabId]; + controller?.dispose(); // 先释放Controller + _tabControllers.remove(tabId); // 移除Controller引用 + _tabs.removeWhere((tab) => tab.id == tabId); // 再移除Tab + if (_activeTabId == tabId) { _activeTabId = _tabs.isNotEmpty ? _tabs.last.id : null; } notifyListeners(); } + void registerController(String tabId, ChangeNotifier controller) { + _tabControllers[tabId] = controller; + } + + T? getController(String tabId) { + return _tabControllers[tabId] as T?; + } + + void disposeController(String tabId) { + _tabControllers[tabId]?.dispose(); + _tabControllers.remove(tabId); + } + void setActiveTab(String tabId) { if (_activeTabId == tabId) return; // 如果已经是活动Tab则不通知 diff --git a/win_text_editor/lib/framework/widgets/tab_view.dart b/win_text_editor/lib/framework/widgets/tab_view.dart index e76ece6..9666a56 100644 --- a/win_text_editor/lib/framework/widgets/tab_view.dart +++ b/win_text_editor/lib/framework/widgets/tab_view.dart @@ -1,34 +1,33 @@ import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; +import 'package:win_text_editor/modules/content_search/controllers/content_search_controller.dart'; import 'package:win_text_editor/shared/components/text_editor.dart'; import 'package:win_text_editor/framework/controllers/tab_manager.dart'; import 'package:win_text_editor/framework/models/tab_model.dart'; import 'package:win_text_editor/modules/content_search/widgets/content_search_view.dart'; -class TabView extends StatelessWidget { +class TabView extends StatefulWidget { final List tabs; final String? currentTabId; const TabView({super.key, required this.tabs, required this.currentTabId}); @override - Widget build(BuildContext context) { - final activeTab = tabs.firstWhere( - (tab) => tab.id == currentTabId, - orElse: () => AppTab(id: '', title: ''), // 提供默认值 - ); + State createState() => _TabViewState(); +} + +class _TabViewState extends State { + // 缓存已创建的视图 + final Map _viewCache = {}; + @override + Widget build(BuildContext context) { return Column( children: [ // 选项卡标签栏 _buildTabBar(context), // 选项卡内容区 - Expanded( - child: - activeTab.id.isNotEmpty - ? _buildTabContent(activeTab) - : const Center(child: Text('无活动标签页')), - ), + Expanded(child: _buildTabContent()), ], ); } @@ -38,12 +37,12 @@ class TabView extends StatelessWidget { height: 40, child: ListView.builder( scrollDirection: Axis.horizontal, - itemCount: tabs.length, + itemCount: widget.tabs.length, itemBuilder: (ctx, index) { - final tab = tabs[index]; + final tab = widget.tabs[index]; return _TabItem( tab: tab, - isActive: tab.id == currentTabId, + isActive: tab.id == widget.currentTabId, onClose: () => context.read().closeTab(tab.id), onTap: () => context.read().setActiveTab(tab.id), ); @@ -52,16 +51,30 @@ class TabView extends StatelessWidget { ); } - Widget _buildTabContent(AppTab tab) { + Widget _buildTabContent() { + final tabManager = Provider.of(context, listen: false); + final activeIndex = widget.tabs.indexWhere((t) => t.id == widget.currentTabId); + if (activeIndex == -1) return const Center(child: Text('无活动标签页')); + return IndexedStack( - index: tabs.indexWhere((tab) => tab.id == currentTabId).clamp(0, tabs.length - 1), + index: activeIndex, children: - tabs.map((tab) { - return findActiveView(tab); + widget.tabs.map((tab) { + final controller = tabManager.getController(tab.id); + return KeyedSubtree(key: ValueKey(tab.id), child: _buildTabItem(tab, controller)); }).toList(), ); } + Widget _buildTabItem(AppTab tab, ContentSearchController? controller) { + switch (tab.type) { + case 'content_search': + return ContentSearchView(tabId: tab.id, controller: controller); + default: + return TextEditor(tabId: tab.id, initialContent: tab.content); + } + } + // 查找当前活动的视图 Widget findActiveView(AppTab tab) { switch (tab.type) { diff --git a/win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart b/win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart index 5e7c7a6..54f1e05 100644 --- a/win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart +++ b/win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart @@ -1,18 +1,15 @@ // content_search_controller.dart import 'dart:async'; -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/framework/controllers/tab_manager.dart'; import 'package:win_text_editor/framework/controllers/logger.dart'; import 'package:win_text_editor/modules/content_search/models/search_mode.dart'; import 'package:win_text_editor/modules/content_search/models/search_result.dart'; import '../services/content_search_service.dart'; -import 'package:flutter_js/flutter_js.dart'; class ContentSearchController with ChangeNotifier { final TabManager tabManager; @@ -26,11 +23,8 @@ class ContentSearchController with ChangeNotifier { bool _customRule = false; SearchMode _searchMode = SearchMode.locate; final List _results = []; - late final JavascriptRuntime _jsRuntime; - ContentSearchController({required this.tabManager}) { - _jsRuntime = getJavascriptRuntime(); - } + ContentSearchController({required this.tabManager}); // Getters String get searchQuery => _searchQuery; diff --git a/win_text_editor/lib/modules/content_search/widgets/content_search_view.dart b/win_text_editor/lib/modules/content_search/widgets/content_search_view.dart index 5a0bcd9..ec83852 100644 --- a/win_text_editor/lib/modules/content_search/widgets/content_search_view.dart +++ b/win_text_editor/lib/modules/content_search/widgets/content_search_view.dart @@ -8,7 +8,9 @@ import 'search_settings.dart'; import 'results_view.dart'; class ContentSearchView extends BaseView { - const ContentSearchView({super.key, required String tabId}) : super(tabId: tabId); + final ContentSearchController? controller; + const ContentSearchView({super.key, required String tabId, this.controller}) + : super(tabId: tabId); @override ContentSearchViewState createState() => ContentSearchViewState(); @@ -19,13 +21,20 @@ class ContentSearchViewState extends BaseViewState { @override void initState() { + print('Initializing ContentSearchViewState, tabId: ${widget.tabId}'); super.initState(); - _controller = ContentSearchController(tabManager: tabManager); + _controller = + tabManager.getController(widget.tabId) ?? ContentSearchController(tabManager: tabManager); + + // 注册Controller到TabManager + if ((widget as ContentSearchView).controller == null) { + tabManager.registerController(widget.tabId, _controller); + } } @override void dispose() { - _controller.dispose(); // 清理控制器 + print('dispose ContentSearchViewState, tabId: ${widget.tabId}'); super.dispose(); }