ftreeview 0.1.3 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +31 -1
- package/package.json +1 -1
- package/src/App.jsx +25 -2
- package/src/components/StatusBar.jsx +13 -1
package/dist/cli.js
CHANGED
|
@@ -350,6 +350,7 @@ function StatusBar({
|
|
|
350
350
|
isGitRepo = false,
|
|
351
351
|
gitSummary = "",
|
|
352
352
|
showHelp = true,
|
|
353
|
+
eventMessage = "",
|
|
353
354
|
termWidth = 80,
|
|
354
355
|
iconSet = "emoji",
|
|
355
356
|
theme = VSCODE_THEME
|
|
@@ -421,6 +422,14 @@ function StatusBar({
|
|
|
421
422
|
paddingX: 1,
|
|
422
423
|
children: /* @__PURE__ */ jsx3(Text3, { ...finalTheme.statusBar.hintStyle, children: "q quit \u2191\u2193/jk move \u2190\u2192/hl expand space toggle r refresh" })
|
|
423
424
|
}
|
|
425
|
+
),
|
|
426
|
+
eventMessage && /* @__PURE__ */ jsx3(
|
|
427
|
+
Box3,
|
|
428
|
+
{
|
|
429
|
+
width: termWidth,
|
|
430
|
+
paddingX: 1,
|
|
431
|
+
children: /* @__PURE__ */ jsx3(Text3, { color: "magenta", bold: true, children: eventMessage })
|
|
432
|
+
}
|
|
424
433
|
)
|
|
425
434
|
] });
|
|
426
435
|
}
|
|
@@ -1474,11 +1483,23 @@ function setupCleanExit() {
|
|
|
1474
1483
|
process.off("SIGINT", onSigint);
|
|
1475
1484
|
};
|
|
1476
1485
|
}
|
|
1486
|
+
function formatWatcherEventMessage(event, relativePath) {
|
|
1487
|
+
if (!relativePath) {
|
|
1488
|
+
return "";
|
|
1489
|
+
}
|
|
1490
|
+
if (event === "add") return `=> File created at ${relativePath}`;
|
|
1491
|
+
if (event === "change") return `=> File modified at ${relativePath}`;
|
|
1492
|
+
if (event === "addDir") return `=> Folder created at ${relativePath}`;
|
|
1493
|
+
if (event === "unlink") return `=> File deleted at ${relativePath}`;
|
|
1494
|
+
if (event === "unlinkDir") return `=> Folder deleted at ${relativePath}`;
|
|
1495
|
+
return "";
|
|
1496
|
+
}
|
|
1477
1497
|
function App({ rootPath, options = {}, version }) {
|
|
1478
1498
|
const rootAbsPath = resolve2(rootPath);
|
|
1479
1499
|
const iconSet = resolveIconSet({ cliIconSet: options.iconSet, noIcons: options.noIcons });
|
|
1480
1500
|
const theme = getTheme(resolveThemeName({ cliTheme: options.theme }));
|
|
1481
1501
|
const [selectedPath, setSelectedPath] = useState6(null);
|
|
1502
|
+
const [recentEventMessage, setRecentEventMessage] = useState6("");
|
|
1482
1503
|
useEffect5(() => setupCleanExit(), []);
|
|
1483
1504
|
const { tree, flatList, refreshFlatList, rebuildTree, ensureChildrenLoaded } = useTree(rootPath, options);
|
|
1484
1505
|
const { statusMap, pathStatusMap, isGitRepo, refresh: refreshGit } = useGitStatus(
|
|
@@ -1554,6 +1575,7 @@ function App({ rootPath, options = {}, version }) {
|
|
|
1554
1575
|
const handleTreeChange = useCallback5((eventsOrEvent, watchPath) => {
|
|
1555
1576
|
const batch = Array.isArray(eventsOrEvent) ? eventsOrEvent : [{ event: eventsOrEvent, path: watchPath }];
|
|
1556
1577
|
let hasStructuralChange = false;
|
|
1578
|
+
let latestEventMessage = "";
|
|
1557
1579
|
for (const item of batch) {
|
|
1558
1580
|
if (!item) continue;
|
|
1559
1581
|
if (item.event === "add" || item.event === "addDir" || item.event === "unlink" || item.event === "unlinkDir") {
|
|
@@ -1561,10 +1583,17 @@ function App({ rootPath, options = {}, version }) {
|
|
|
1561
1583
|
}
|
|
1562
1584
|
const changeStatus = mapWatcherEventToChangeStatus(item.event);
|
|
1563
1585
|
const relativePath = toTreeRelativePath(item.path);
|
|
1586
|
+
const eventMessage = formatWatcherEventMessage(item.event, relativePath);
|
|
1587
|
+
if (eventMessage) {
|
|
1588
|
+
latestEventMessage = eventMessage;
|
|
1589
|
+
}
|
|
1564
1590
|
if (changeStatus && relativePath) {
|
|
1565
1591
|
markChanged(relativePath, changeStatus);
|
|
1566
1592
|
}
|
|
1567
1593
|
}
|
|
1594
|
+
if (latestEventMessage) {
|
|
1595
|
+
setRecentEventMessage(latestEventMessage);
|
|
1596
|
+
}
|
|
1568
1597
|
if (hasStructuralChange) {
|
|
1569
1598
|
rebuildTree(true);
|
|
1570
1599
|
}
|
|
@@ -1580,7 +1609,7 @@ function App({ rootPath, options = {}, version }) {
|
|
|
1580
1609
|
noWatch: options.noWatch
|
|
1581
1610
|
});
|
|
1582
1611
|
const helpEnabled = options.help !== false;
|
|
1583
|
-
const statusBarHeight = helpEnabled ?
|
|
1612
|
+
const statusBarHeight = 1 + (helpEnabled ? 1 : 0) + (recentEventMessage ? 1 : 0);
|
|
1584
1613
|
const viewportHeight = termSize.height - statusBarHeight;
|
|
1585
1614
|
const termWidth = termSize.width;
|
|
1586
1615
|
const { fileCount, dirCount } = calculateCounts(flatList);
|
|
@@ -1610,6 +1639,7 @@ function App({ rootPath, options = {}, version }) {
|
|
|
1610
1639
|
isGitRepo,
|
|
1611
1640
|
gitSummary,
|
|
1612
1641
|
showHelp: helpEnabled,
|
|
1642
|
+
eventMessage: recentEventMessage,
|
|
1613
1643
|
termWidth,
|
|
1614
1644
|
iconSet,
|
|
1615
1645
|
theme
|
package/package.json
CHANGED
package/src/App.jsx
CHANGED
|
@@ -52,6 +52,18 @@ function setupCleanExit() {
|
|
|
52
52
|
};
|
|
53
53
|
}
|
|
54
54
|
|
|
55
|
+
function formatWatcherEventMessage(event, relativePath) {
|
|
56
|
+
if (!relativePath) {
|
|
57
|
+
return '';
|
|
58
|
+
}
|
|
59
|
+
if (event === 'add') return `=> File created at ${relativePath}`;
|
|
60
|
+
if (event === 'change') return `=> File modified at ${relativePath}`;
|
|
61
|
+
if (event === 'addDir') return `=> Folder created at ${relativePath}`;
|
|
62
|
+
if (event === 'unlink') return `=> File deleted at ${relativePath}`;
|
|
63
|
+
if (event === 'unlinkDir') return `=> Folder deleted at ${relativePath}`;
|
|
64
|
+
return '';
|
|
65
|
+
}
|
|
66
|
+
|
|
55
67
|
/**
|
|
56
68
|
* App Component Props
|
|
57
69
|
* @property {string} rootPath - Root directory path to explore
|
|
@@ -64,6 +76,7 @@ export default function App({ rootPath, options = {}, version }) {
|
|
|
64
76
|
|
|
65
77
|
// Track selected path to preserve cursor position across rebuilds
|
|
66
78
|
const [selectedPath, setSelectedPath] = useState(null);
|
|
79
|
+
const [recentEventMessage, setRecentEventMessage] = useState('');
|
|
67
80
|
|
|
68
81
|
// Setup clean exit handler - ensures proper terminal state on exit
|
|
69
82
|
useEffect(() => setupCleanExit(), []);
|
|
@@ -179,6 +192,7 @@ export default function App({ rootPath, options = {}, version }) {
|
|
|
179
192
|
: [{ event: eventsOrEvent, path: watchPath }];
|
|
180
193
|
|
|
181
194
|
let hasStructuralChange = false;
|
|
195
|
+
let latestEventMessage = '';
|
|
182
196
|
|
|
183
197
|
for (const item of batch) {
|
|
184
198
|
if (!item) continue;
|
|
@@ -187,12 +201,20 @@ export default function App({ rootPath, options = {}, version }) {
|
|
|
187
201
|
}
|
|
188
202
|
const changeStatus = mapWatcherEventToChangeStatus(item.event);
|
|
189
203
|
const relativePath = toTreeRelativePath(item.path);
|
|
204
|
+
const eventMessage = formatWatcherEventMessage(item.event, relativePath);
|
|
205
|
+
if (eventMessage) {
|
|
206
|
+
latestEventMessage = eventMessage;
|
|
207
|
+
}
|
|
190
208
|
|
|
191
209
|
if (changeStatus && relativePath) {
|
|
192
210
|
markChanged(relativePath, changeStatus);
|
|
193
211
|
}
|
|
194
212
|
}
|
|
195
213
|
|
|
214
|
+
if (latestEventMessage) {
|
|
215
|
+
setRecentEventMessage(latestEventMessage);
|
|
216
|
+
}
|
|
217
|
+
|
|
196
218
|
if (hasStructuralChange) {
|
|
197
219
|
rebuildTree(true);
|
|
198
220
|
}
|
|
@@ -212,9 +234,9 @@ export default function App({ rootPath, options = {}, version }) {
|
|
|
212
234
|
});
|
|
213
235
|
|
|
214
236
|
// Calculate viewport dimensions
|
|
215
|
-
// Reserve space: 1 line
|
|
237
|
+
// Reserve space: 1 main status line + optional hints line + optional event line.
|
|
216
238
|
const helpEnabled = options.help !== false; // Show help by default
|
|
217
|
-
const statusBarHeight = helpEnabled ?
|
|
239
|
+
const statusBarHeight = 1 + (helpEnabled ? 1 : 0) + (recentEventMessage ? 1 : 0);
|
|
218
240
|
const viewportHeight = termSize.height - statusBarHeight;
|
|
219
241
|
const termWidth = termSize.width;
|
|
220
242
|
|
|
@@ -250,6 +272,7 @@ export default function App({ rootPath, options = {}, version }) {
|
|
|
250
272
|
isGitRepo={isGitRepo}
|
|
251
273
|
gitSummary={gitSummary}
|
|
252
274
|
showHelp={helpEnabled}
|
|
275
|
+
eventMessage={recentEventMessage}
|
|
253
276
|
termWidth={termWidth}
|
|
254
277
|
iconSet={iconSet}
|
|
255
278
|
theme={theme}
|
|
@@ -120,6 +120,7 @@ export function calculateGitStatus(statusMap) {
|
|
|
120
120
|
* @property {boolean} isGitRepo - Whether current directory is a git repo
|
|
121
121
|
* @property {string} gitSummary - Git status summary (e.g., "clean" or "3M 1A")
|
|
122
122
|
* @property {boolean} showHelp - Show keybind hints
|
|
123
|
+
* @property {string} eventMessage - Latest filesystem event message
|
|
123
124
|
* @property {number} termWidth - Terminal width in columns
|
|
124
125
|
*/
|
|
125
126
|
export function StatusBar({
|
|
@@ -132,6 +133,7 @@ export function StatusBar({
|
|
|
132
133
|
isGitRepo = false,
|
|
133
134
|
gitSummary = '',
|
|
134
135
|
showHelp = true,
|
|
136
|
+
eventMessage = '',
|
|
135
137
|
termWidth = 80,
|
|
136
138
|
iconSet = 'emoji',
|
|
137
139
|
theme = VSCODE_THEME,
|
|
@@ -230,7 +232,6 @@ export function StatusBar({
|
|
|
230
232
|
)}
|
|
231
233
|
</Box>
|
|
232
234
|
|
|
233
|
-
{/* Keybind hints line (optional) */}
|
|
234
235
|
{showHelp && (
|
|
235
236
|
<Box
|
|
236
237
|
width={termWidth}
|
|
@@ -241,6 +242,17 @@ export function StatusBar({
|
|
|
241
242
|
</Text>
|
|
242
243
|
</Box>
|
|
243
244
|
)}
|
|
245
|
+
|
|
246
|
+
{eventMessage && (
|
|
247
|
+
<Box
|
|
248
|
+
width={termWidth}
|
|
249
|
+
paddingX={1}
|
|
250
|
+
>
|
|
251
|
+
<Text color="magenta" bold>
|
|
252
|
+
{eventMessage}
|
|
253
|
+
</Text>
|
|
254
|
+
</Box>
|
|
255
|
+
)}
|
|
244
256
|
</Box>
|
|
245
257
|
);
|
|
246
258
|
}
|