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'; @@ -5,6 +5,7 @@ import 'package:win_text_editor/framework/controllers/logger.dart';
class TabManager with ChangeNotifier {
final List<AppTab> _tabs = [];
final Map<String, ChangeNotifier> _tabControllers = {}; // Tab的Controller
String? _activeTabId;
List<AppTab> get tabs => _tabs;
@ -28,11 +29,15 @@ class TabManager with ChangeNotifier { @@ -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 { @@ -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<T extends ChangeNotifier>(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则不通知

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

@ -1,34 +1,33 @@ @@ -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<AppTab> 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<TabView> createState() => _TabViewState();
}
class _TabViewState extends State<TabView> {
//
final Map<String, Widget> _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 { @@ -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<TabManager>().closeTab(tab.id),
onTap: () => context.read<TabManager>().setActiveTab(tab.id),
);
@ -52,16 +51,30 @@ class TabView extends StatelessWidget { @@ -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(
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<ContentSearchController>(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) {

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

@ -1,18 +1,15 @@ @@ -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 { @@ -26,11 +23,8 @@ class ContentSearchController with ChangeNotifier {
bool _customRule = false;
SearchMode _searchMode = SearchMode.locate;
final List<SearchResult> _results = [];
late final JavascriptRuntime _jsRuntime;
ContentSearchController({required this.tabManager}) {
_jsRuntime = getJavascriptRuntime();
}
ContentSearchController({required this.tabManager});
// Getters
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'; @@ -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 { @@ -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();
}

Loading…
Cancel
Save