Browse Source

tab标签关闭基本正常

master
hejl 2 months ago
parent
commit
2da9e4204f
  1. 26
      win_text_editor/lib/framework/controllers/tab_manager.dart
  2. 51
      win_text_editor/lib/framework/widgets/tab_view.dart
  3. 8
      win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart
  4. 15
      win_text_editor/lib/modules/content_search/widgets/content_search_view.dart

26
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 { class TabManager with ChangeNotifier {
final List<AppTab> _tabs = []; final List<AppTab> _tabs = [];
final Map<String, ChangeNotifier> _tabControllers = {}; // Tab的Controller
String? _activeTabId; String? _activeTabId;
List<AppTab> get tabs => _tabs; List<AppTab> get tabs => _tabs;
@ -28,11 +29,15 @@ class TabManager with ChangeNotifier {
String? type, String? type,
IconData? icon, IconData? icon,
String content = '', String content = '',
ChangeNotifier? controller,
}) async { }) async {
final newTab = AppTab(id: id, title: title, type: type, icon: icon, content: content); final newTab = AppTab(id: id, title: title, type: type, icon: icon, content: content);
_tabs.add(newTab); _tabs.add(newTab);
_activeTabId = newTab.id; if (controller != null) {
_tabControllers[id] = controller;
}
_activeTabId = id;
notifyListeners(); notifyListeners();
} }
@ -47,13 +52,30 @@ class TabManager with ChangeNotifier {
void closeTab(String tabId) { void closeTab(String tabId) {
Logger().info('关闭选项卡: $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) { if (_activeTabId == tabId) {
_activeTabId = _tabs.isNotEmpty ? _tabs.last.id : null; _activeTabId = _tabs.isNotEmpty ? _tabs.last.id : null;
} }
notifyListeners(); notifyListeners();
} }
void registerController(String tabId, ChangeNotifier controller) {
_tabControllers[tabId] = controller;
}
T? getController<T extends ChangeNotifier>(String tabId) {
return _tabControllers[tabId] as T?;
}
void disposeController(String tabId) {
_tabControllers[tabId]?.dispose();
_tabControllers.remove(tabId);
}
void setActiveTab(String tabId) { void setActiveTab(String tabId) {
if (_activeTabId == tabId) return; // Tab则不通知 if (_activeTabId == tabId) return; // Tab则不通知

51
win_text_editor/lib/framework/widgets/tab_view.dart

@ -1,34 +1,33 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:provider/provider.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/shared/components/text_editor.dart';
import 'package:win_text_editor/framework/controllers/tab_manager.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/framework/models/tab_model.dart';
import 'package:win_text_editor/modules/content_search/widgets/content_search_view.dart'; import 'package:win_text_editor/modules/content_search/widgets/content_search_view.dart';
class TabView extends StatelessWidget { class TabView extends StatefulWidget {
final List<AppTab> tabs; final List<AppTab> tabs;
final String? currentTabId; final String? currentTabId;
const TabView({super.key, required this.tabs, required this.currentTabId}); const TabView({super.key, required this.tabs, required this.currentTabId});
@override @override
Widget build(BuildContext context) { State<TabView> createState() => _TabViewState();
final activeTab = tabs.firstWhere( }
(tab) => tab.id == currentTabId,
orElse: () => AppTab(id: '', title: ''), // class _TabViewState extends State<TabView> {
); //
final Map<String, Widget> _viewCache = {};
@override
Widget build(BuildContext context) {
return Column( return Column(
children: [ children: [
// //
_buildTabBar(context), _buildTabBar(context),
// //
Expanded( Expanded(child: _buildTabContent()),
child:
activeTab.id.isNotEmpty
? _buildTabContent(activeTab)
: const Center(child: Text('无活动标签页')),
),
], ],
); );
} }
@ -38,12 +37,12 @@ class TabView extends StatelessWidget {
height: 40, height: 40,
child: ListView.builder( child: ListView.builder(
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
itemCount: tabs.length, itemCount: widget.tabs.length,
itemBuilder: (ctx, index) { itemBuilder: (ctx, index) {
final tab = tabs[index]; final tab = widget.tabs[index];
return _TabItem( return _TabItem(
tab: tab, tab: tab,
isActive: tab.id == currentTabId, isActive: tab.id == widget.currentTabId,
onClose: () => context.read<TabManager>().closeTab(tab.id), onClose: () => context.read<TabManager>().closeTab(tab.id),
onTap: () => context.read<TabManager>().setActiveTab(tab.id), onTap: () => context.read<TabManager>().setActiveTab(tab.id),
); );
@ -52,16 +51,30 @@ class TabView extends StatelessWidget {
); );
} }
Widget _buildTabContent(AppTab tab) { Widget _buildTabContent() {
final tabManager = Provider.of<TabManager>(context, listen: false);
final activeIndex = widget.tabs.indexWhere((t) => t.id == widget.currentTabId);
if (activeIndex == -1) return const Center(child: Text('无活动标签页'));
return IndexedStack( return IndexedStack(
index: tabs.indexWhere((tab) => tab.id == currentTabId).clamp(0, tabs.length - 1), index: activeIndex,
children: children:
tabs.map((tab) { widget.tabs.map((tab) {
return findActiveView(tab); final controller = tabManager.getController<ContentSearchController>(tab.id);
return KeyedSubtree(key: ValueKey(tab.id), child: _buildTabItem(tab, controller));
}).toList(), }).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) { Widget findActiveView(AppTab tab) {
switch (tab.type) { switch (tab.type) {

8
win_text_editor/lib/modules/content_search/controllers/content_search_controller.dart

@ -1,18 +1,15 @@
// content_search_controller.dart // content_search_controller.dart
import 'dart:async'; import 'dart:async';
import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:file_picker/file_picker.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/tab_manager.dart';
import 'package:win_text_editor/framework/controllers/logger.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_mode.dart';
import 'package:win_text_editor/modules/content_search/models/search_result.dart'; import 'package:win_text_editor/modules/content_search/models/search_result.dart';
import '../services/content_search_service.dart'; import '../services/content_search_service.dart';
import 'package:flutter_js/flutter_js.dart';
class ContentSearchController with ChangeNotifier { class ContentSearchController with ChangeNotifier {
final TabManager tabManager; final TabManager tabManager;
@ -26,11 +23,8 @@ class ContentSearchController with ChangeNotifier {
bool _customRule = false; bool _customRule = false;
SearchMode _searchMode = SearchMode.locate; SearchMode _searchMode = SearchMode.locate;
final List<SearchResult> _results = []; final List<SearchResult> _results = [];
late final JavascriptRuntime _jsRuntime;
ContentSearchController({required this.tabManager}) { ContentSearchController({required this.tabManager});
_jsRuntime = getJavascriptRuntime();
}
// Getters // Getters
String get searchQuery => _searchQuery; String get searchQuery => _searchQuery;

15
win_text_editor/lib/modules/content_search/widgets/content_search_view.dart

@ -8,7 +8,9 @@ import 'search_settings.dart';
import 'results_view.dart'; import 'results_view.dart';
class ContentSearchView extends BaseView { 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 @override
ContentSearchViewState createState() => ContentSearchViewState(); ContentSearchViewState createState() => ContentSearchViewState();
@ -19,13 +21,20 @@ class ContentSearchViewState extends BaseViewState {
@override @override
void initState() { void initState() {
print('Initializing ContentSearchViewState, tabId: ${widget.tabId}');
super.initState(); 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 @override
void dispose() { void dispose() {
_controller.dispose(); // print('dispose ContentSearchViewState, tabId: ${widget.tabId}');
super.dispose(); super.dispose();
} }

Loading…
Cancel
Save