mp-lens
Version:
微信小程序分析工具 (Unused Code, Dependencies, Visualization)
147 lines • 10.3 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileListView = FileListView;
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 import path
const FileListView_module_css_1 = __importDefault(require("./FileListView.module.css")); // Import CSS Module
// ADD HELPER: Get file extension from path
function getFileExtension(path) {
const match = path.match(/\.([^./\\]+)$/);
return match ? match[1].toLowerCase() : ''; // Ensure lowercase extension
}
// ADD HELPER: Convert absolute path to relative path
function toRelativePath(absPath, root) {
if (!absPath || !root)
return absPath;
// Normalize path separators to forward slashes
const normAbs = absPath.replace(/\\/g, '/');
const normRoot = root.replace(/\\/g, '/').replace(/\/$/, ''); // Ensure no trailing slash
if (normAbs.startsWith(normRoot + '/')) {
// Check if it starts with root + slash
return normAbs.slice(normRoot.length + 1); // Remove root + leading slash
}
return absPath; // Return original if not under root
}
/**
* A component that displays a list of all files in the current node
*/
function FileListView({ node, onFileSelect }) {
var _a;
// State for sorting: null means default sort (path), otherwise sort by the active column
const [sizeOrder, setSizeOrder] = (0, hooks_1.useState)('desc');
const [dependencyCountOrder, setDependencyCountOrder] = (0, hooks_1.useState)(null);
const [filterType, setFilterType] = (0, hooks_1.useState)(''); // '' means show all
// Use full graph data if available
const fullGraphData = window.__MP_LENS_GRAPH_DATA__ || { nodes: [], links: [], miniappRoot: '' };
const miniappRoot = fullGraphData.miniappRoot || '';
// Pre-calculate dependency counts for all nodes
const dependencyCounts = (0, hooks_1.useMemo)(() => {
const counts = new Map();
for (const link of fullGraphData.links) {
counts.set(link.target, (counts.get(link.target) || 0) + 1);
}
return counts;
}, [fullGraphData.links]);
// Collect all reachable module files first
const allFiles = (0, hooks_1.useMemo)(() => {
var _a;
const moduleIds = ((_a = node.properties) === null || _a === void 0 ? void 0 : _a.reachableModuleIds) || new Set();
const nodeMap = new Map(fullGraphData.nodes.map((n) => [n.id, n])); // Use GraphNode type
const files = []; // Use FileDetail type
let counter = 0;
moduleIds.forEach((mid) => {
var _a, _b;
const m = nodeMap.get(mid);
if (!m || m.type !== 'Module')
return;
const path = m.id;
const relativePath = toRelativePath(path, miniappRoot);
const size = ((_a = m.properties) === null || _a === void 0 ? void 0 : _a.fileSize) || 0;
const ext = ((_b = m.properties) === null || _b === void 0 ? void 0 : _b.fileExt) || getFileExtension(path) || 'unknown';
const dependencyCount = dependencyCounts.get(mid) || 0;
files.push({
id: ++counter,
path,
relativePath,
size,
type: ext,
dependencyCount,
});
});
return files.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
}, [
node.id,
(_a = node.properties) === null || _a === void 0 ? void 0 : _a.reachableModuleIds,
fullGraphData.nodes,
miniappRoot,
dependencyCounts,
]); // Added dependencies
// Get unique file types for filtering options
const uniqueFileTypes = (0, hooks_1.useMemo)(() => {
const types = new Set(allFiles.map((f) => f.type));
return Array.from(types).sort();
}, [allFiles]);
// Calculate file counts for each type
const fileCountsByType = (0, hooks_1.useMemo)(() => {
const counts = {};
for (const file of allFiles) {
counts[file.type] = (counts[file.type] || 0) + 1;
}
return counts;
}, [allFiles]);
// Filter and sort files based on state
const displayedFiles = (0, hooks_1.useMemo)(() => {
let files = allFiles;
// Apply filter
if (filterType) {
files = files.filter((f) => f.type === filterType);
}
// Apply sorting based on which column header was clicked last
files.sort((a, b) => {
if (dependencyCountOrder) {
// Sort by dependency count
return dependencyCountOrder === 'asc'
? a.dependencyCount - b.dependencyCount
: b.dependencyCount - a.dependencyCount;
}
else if (sizeOrder) {
// Sort by size
return sizeOrder === 'asc' ? a.size - b.size : b.size - a.size;
}
else {
// Default sort by relative path if no column is active
return a.relativePath.localeCompare(b.relativePath);
}
});
// Re-assign sequential IDs after filtering and sorting
return files.map((f, idx) => ({ ...f, id: idx + 1 }));
}, [allFiles, filterType, sizeOrder, dependencyCountOrder]); // Add dependencyCountOrder dependency
// If no files are found *after filtering* (or initially), show a message
if (displayedFiles.length === 0 && allFiles.length === 0) {
return ((0, jsx_runtime_1.jsx)("div", { className: FileListView_module_css_1.default.fileListView, children: (0, jsx_runtime_1.jsx)("div", { className: FileListView_module_css_1.default.emptyState, children: (0, jsx_runtime_1.jsx)("p", { children: "\u6B64\u8282\u70B9\u6CA1\u6709\u76F4\u63A5\u5173\u8054\u7684\u6587\u4EF6\u3002" }) }) }));
}
// Sorting arrows - display only if the column is actively sorted
const sizeArrow = sizeOrder ? (sizeOrder === 'asc' ? '↑' : '↓') : '';
const dependencyCountArrow = dependencyCountOrder
? dependencyCountOrder === 'asc'
? '↑'
: '↓'
: '';
const handleSizeSortClick = () => {
const newOrder = sizeOrder === 'asc' ? 'desc' : 'asc';
setSizeOrder(newOrder);
setDependencyCountOrder(null); // Reset other sort
};
const handleDependencyCountSortClick = () => {
const newOrder = dependencyCountOrder === 'asc' ? 'desc' : 'asc';
setDependencyCountOrder(newOrder);
setSizeOrder(null); // Reset other sort
};
return ((0, jsx_runtime_1.jsxs)("div", { className: FileListView_module_css_1.default.fileListView, children: [(0, jsx_runtime_1.jsx)("div", { className: FileListView_module_css_1.default.fileListHeader, children: miniappRoot && (0, jsx_runtime_1.jsxs)("div", { className: FileListView_module_css_1.default.rootPath, children: ["\u6839\u76EE\u5F55: ", miniappRoot] }) }), uniqueFileTypes.length > 1 && ( // Only show filters if there's more than one type
(0, jsx_runtime_1.jsxs)("div", { className: FileListView_module_css_1.default.fileFilterControls, children: [(0, jsx_runtime_1.jsx)("span", { children: "\u7B5B\u9009:" }), (0, jsx_runtime_1.jsxs)("button", { onClick: () => setFilterType(''), className: `${FileListView_module_css_1.default.filterButton} ${filterType === '' ? FileListView_module_css_1.default.active : ''}`, children: ["All (", allFiles.length, ")"] }), uniqueFileTypes.map((type) => ((0, jsx_runtime_1.jsxs)("button", { onClick: () => setFilterType(type), className: `${FileListView_module_css_1.default.filterButton} ${filterType === type ? FileListView_module_css_1.default.active : ''}`, title: `.${type}`, children: [".", type, " (", fileCountsByType[type] || 0, ")"] }, type)))] })), (0, jsx_runtime_1.jsx)("div", { className: FileListView_module_css_1.default.fileTableContainer, children: displayedFiles.length > 0 ? ((0, jsx_runtime_1.jsxs)("table", { className: FileListView_module_css_1.default.fileTable, children: [(0, jsx_runtime_1.jsx)("thead", { children: (0, jsx_runtime_1.jsxs)("tr", { children: [(0, jsx_runtime_1.jsx)("th", { className: FileListView_module_css_1.default.sequenceColumn, children: "\u5E8F\u53F7" }), (0, jsx_runtime_1.jsx)("th", { className: FileListView_module_css_1.default.fileColumn, children: "\u6587\u4EF6" }), (0, jsx_runtime_1.jsxs)("th", { className: `${FileListView_module_css_1.default.refCountColumn} ${FileListView_module_css_1.default.sortable}`, style: { cursor: 'pointer' }, onClick: handleDependencyCountSortClick, title: "\u70B9\u51FB\u5207\u6362\u6392\u5E8F", children: ["\u88AB\u4F9D\u8D56\u6B21\u6570 ", dependencyCountArrow] }), (0, jsx_runtime_1.jsxs)("th", { className: `${FileListView_module_css_1.default.sizeColumn} ${FileListView_module_css_1.default.sortable}`, style: { cursor: 'pointer' }, onClick: handleSizeSortClick, title: "\u70B9\u51FB\u5207\u6362\u6392\u5E8F", children: ["\u5927\u5C0F ", sizeArrow] })] }) }), (0, jsx_runtime_1.jsx)("tbody", { children: displayedFiles.map((file) => ((0, jsx_runtime_1.jsxs)("tr", { onClick: () => onFileSelect(file.path), title: `点击跳转到依赖图: ${file.relativePath}`, style: { cursor: 'pointer' }, children: [(0, jsx_runtime_1.jsx)("td", { className: FileListView_module_css_1.default.sequenceColumn, children: file.id }), (0, jsx_runtime_1.jsx)("td", { className: FileListView_module_css_1.default.fileColumn, title: file.path, children: file.relativePath }), (0, jsx_runtime_1.jsx)("td", { className: FileListView_module_css_1.default.refCountColumn, children: file.dependencyCount }), (0, jsx_runtime_1.jsx)("td", { className: FileListView_module_css_1.default.sizeColumn, children: (0, dependency_tree_processor_1.formatBytes)(file.size) })] }, file.path))) })] })) : ((0, jsx_runtime_1.jsx)("div", { className: FileListView_module_css_1.default.emptyState, children: (0, jsx_runtime_1.jsx)("p", { children: "\u6CA1\u6709\u6587\u4EF6\u5339\u914D\u5F53\u524D\u7684\u7B5B\u9009\u6761\u4EF6\u3002" }) })) })] }));
}
//# sourceMappingURL=FileListView.js.map