mp-lens
Version:
微信小程序分析工具 (Unused Code, Dependencies, Visualization)
141 lines • 8.56 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.App = App;
const jsx_runtime_1 = require("preact/jsx-runtime");
const hooks_1 = require("preact/hooks");
const dependency_tree_processor_1 = require("../utils/dependency-tree-processor"); // UPDATED: Removed formatBytes
const DependencyGraph_1 = require("./DependencyGraph");
const FileListView_1 = require("./FileListView");
const Header_1 = require("./Header"); // Import the new Header component
const Layout_module_css_1 = __importDefault(require("./Layout.module.css")); // Import the Layout CSS module
const NodeDetails_1 = require("./NodeDetails");
const Tabs_1 = require("./Tabs");
const TreeView_1 = require("./TreeView");
const UnusedFilesView_1 = require("./UnusedFilesView");
const emptyProjectStructure = {
nodes: [],
links: [],
rootNodeId: null,
miniappRoot: '',
};
const emptyTreeNode = {
id: 'loading',
label: 'Loading tree...',
type: 'Unknown',
properties: { fileCount: 0, totalSize: 0 },
children: [],
};
// Helper function to find a node in the tree by its ID
function findTreeNodeById(treeNode, id) {
if (!treeNode) {
return null;
}
if (treeNode.id === id) {
return treeNode;
}
if (treeNode.children) {
for (const child of treeNode.children) {
const found = findTreeNodeById(child, id);
if (found) {
return found;
}
}
}
return null;
}
function App(props) {
// Accept props object directly
// Log props to satisfy linter if AppProps is empty, can be removed if AppProps gets members
if (Object.keys(props).length > 0) {
console.log('[App] Props received:', props);
}
const fullGraphData = (0, hooks_1.useMemo)(() => window.__MP_LENS_GRAPH_DATA__ || emptyProjectStructure, []);
// Build the tree structure AND calculate stats in one step
const initialTreeData = (0, hooks_1.useMemo)(() => (0, dependency_tree_processor_1.buildTreeWithStats)(fullGraphData) || emptyTreeNode, [fullGraphData]);
const [selectedNode, setSelectedNode] = (0, hooks_1.useState)(initialTreeData);
const [currentMode, setCurrentMode] = (0, hooks_1.useState)('tree');
const [activeTabId, setActiveTabId] = (0, hooks_1.useState)('details'); // Default to details tab
const handleNodeSelect = (node) => {
setSelectedNode(node);
};
const handleGraphNodeSelect = (nodeId) => {
// Find the corresponding node within the constructed tree data
const treeNode = findTreeNodeById(initialTreeData, nodeId);
if (treeNode) {
setSelectedNode(treeNode); // Set the found node from the tree
setCurrentMode('tree');
}
else {
// Fallback or error handling if node not found in the tree
// This might happen if graph data includes nodes not represented in the tree
console.warn(`[App] TreeNode not found in initialTreeData for ID: ${nodeId}. Falling back to graph data.`);
// Optional Fallback: use raw data like before, but be aware it might be incomplete for details view
const nodeData = fullGraphData.nodes.find((n) => n.id === nodeId);
if (nodeData) {
setSelectedNode({
// This fallback node will lack children and accurate calculated stats
id: nodeData.id,
label: nodeData.label,
type: nodeData.type,
properties: nodeData.properties,
});
setCurrentMode('tree');
}
else {
console.error(`[App] GraphNode also not found for ID: ${nodeId}`);
}
}
};
const realUnusedFiles = (0, hooks_1.useMemo)(() => window.__MP_LENS_UNUSED_FILES__ || [], []);
// Calculate root stats using the root of the built tree
const rootStats = (0, hooks_1.useMemo)(() => {
var _a, _b;
const rootNodeForStats = initialTreeData; // Use the root of the built tree
return {
totalFiles: ((_a = rootNodeForStats.properties) === null || _a === void 0 ? void 0 : _a.fileCount) || 0,
totalSize: ((_b = rootNodeForStats.properties) === null || _b === void 0 ? void 0 : _b.totalSize) || 0,
unusedFileCount: realUnusedFiles.length,
unusedFilesList: realUnusedFiles,
};
}, [initialTreeData, realUnusedFiles]);
const switchToUnusedFilesMode = () => setCurrentMode('unusedFiles');
const switchToTreeMode = () => setCurrentMode('tree');
// Handler for when a file is clicked in FileListView
const handleFileSelect = (moduleId) => {
handleGraphNodeSelect(moduleId); // Reuse existing logic to select the node
setActiveTabId('graph'); // Switch to the graph tab
};
// Handler for when a child node is clicked in NodeDetails view
const handleChildNodeGraphJump = (nodeId) => {
handleGraphNodeSelect(nodeId);
setActiveTabId('graph');
};
if (initialTreeData.id === 'loading' ||
initialTreeData.id === 'empty' ||
initialTreeData.id === 'error_root') {
return ((0, jsx_runtime_1.jsxs)("div", { className: Layout_module_css_1.default.appContainer, children: [(0, jsx_runtime_1.jsx)(Header_1.Header, { title: window.__MP_LENS_TITLE__ || '依赖可视化', totalFiles: 0, totalSize: 0, unusedFileCount: 0, onTreeModeClick: () => { }, onUnusedFilesClick: () => { } }), (0, jsx_runtime_1.jsx)("main", { className: Layout_module_css_1.default.mainContainer, children: (0, jsx_runtime_1.jsx)("section", { className: Layout_module_css_1.default.content, style: { display: 'flex', justifyContent: 'center', alignItems: 'center' }, children: (0, jsx_runtime_1.jsx)("p", { children: initialTreeData.label }) }) })] }));
}
// Create class name for main container with mode
const mainContainerClassName = `${Layout_module_css_1.default.mainContainer} ${currentMode === 'unusedFiles' ? Layout_module_css_1.default.modeUnusedFiles : ''}`;
return ((0, jsx_runtime_1.jsxs)("div", { className: Layout_module_css_1.default.appContainer, children: [(0, jsx_runtime_1.jsx)(Header_1.Header, { title: window.__MP_LENS_TITLE__ || '依赖可视化', totalFiles: rootStats.totalFiles, totalSize: rootStats.totalSize, unusedFileCount: rootStats.unusedFileCount, onTreeModeClick: switchToTreeMode, onUnusedFilesClick: switchToUnusedFilesMode }), (0, jsx_runtime_1.jsxs)("main", { className: mainContainerClassName, children: [currentMode === 'tree' && ((0, jsx_runtime_1.jsx)("aside", { className: Layout_module_css_1.default.sidebar, children: (0, jsx_runtime_1.jsx)(TreeView_1.TreeView, { data: initialTreeData, onNodeSelect: handleNodeSelect, selectedNodeId: selectedNode.id }) })), (0, jsx_runtime_1.jsx)("section", { className: Layout_module_css_1.default.content, children: currentMode === 'tree' ? ((0, jsx_runtime_1.jsx)(Tabs_1.Tabs, { tabs: [
{
id: 'details',
label: '节点详情',
content: ((0, jsx_runtime_1.jsx)(NodeDetails_1.NodeDetails, { node: selectedNode, fullGraphData: fullGraphData, onChildNodeSelect: handleChildNodeGraphJump })),
},
{
id: 'graph',
label: '依赖图',
content: ((0, jsx_runtime_1.jsx)(DependencyGraph_1.DependencyGraph, { selectedNode: selectedNode, fullGraphData: fullGraphData, initialTreeData: initialTreeData, onNodeSelect: handleGraphNodeSelect })),
},
{
id: 'filelist',
label: '文件列表',
content: (0, jsx_runtime_1.jsx)(FileListView_1.FileListView, { node: selectedNode, onFileSelect: handleFileSelect }), // Pass handler
},
], activeTabId: activeTabId, onTabChange: setActiveTabId })) : ((0, jsx_runtime_1.jsx)(UnusedFilesView_1.UnusedFilesView, { unusedFiles: rootStats.unusedFilesList, onReturnToTree: switchToTreeMode })) })] })] }));
}
//# sourceMappingURL=App.js.map