@danixl30/file-explorer-cli 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- package/LICENSE +21 -0
- package/dist/alerts/AlertContextProvider.js +13 -0
- package/dist/alerts/components/AlertDisplay.js +19 -0
- package/dist/alerts/logic/alert.logic.js +16 -0
- package/dist/app.js +27 -0
- package/dist/bookmark/Bookmark.js +123 -0
- package/dist/bookmark/components/BookmarkList.js +47 -0
- package/dist/bookmark/context/BookmarkPaneContext.js +9 -0
- package/dist/bookmark/events/add.item.js +8 -0
- package/dist/bookmark/implementations/clean.bookmarks.js +6 -0
- package/dist/bookmark/implementations/get.all.bookmarks.js +2 -0
- package/dist/bookmark/implementations/save.bookmarks.js +5 -0
- package/dist/bookmark/logic/bookmark.manager.js +25 -0
- package/dist/bookmark/services/clean.bookmarks.js +1 -0
- package/dist/bookmark/services/get.all.bookmarks.js +1 -0
- package/dist/bookmark/services/write.bookmarks.js +1 -0
- package/dist/bookmark/types/bookmark.js +1 -0
- package/dist/cli.js +31 -0
- package/dist/clipboard/ClipboardProvider.js +8 -0
- package/dist/clipboard/logic/clipboard-logic.js +10 -0
- package/dist/core/application/event-handler/event-handler.js +1 -0
- package/dist/core/application/event-handler/listener/event-listener.js +1 -0
- package/dist/core/application/event-handler/types/event.js +1 -0
- package/dist/core/application/event-handler/types/subscription.js +1 -0
- package/dist/core/application/id-generator/id.generator.js +1 -0
- package/dist/core/application/init-layout/init-layout.js +1 -0
- package/dist/core/application/input-manager/input-manager.js +1 -0
- package/dist/core/application/input-manager/types/input-manager-result.js +1 -0
- package/dist/core/application/on-init/on-init.js +1 -0
- package/dist/core/application/on-init-job/lazy/on-init-job-lazy.js +1 -0
- package/dist/core/application/on-init-job/on-init-job.js +1 -0
- package/dist/core/application/pagination-manager/pagination-manager.js +1 -0
- package/dist/core/application/pagination-manager/types/pagination-result.js +1 -0
- package/dist/core/application/service/application-service.js +1 -0
- package/dist/core/application/state/state-factory.js +1 -0
- package/dist/core/application/state/state-provider.js +1 -0
- package/dist/core/application/state-observers/state-observer.js +1 -0
- package/dist/core/application/timer/sleep/sleep.js +1 -0
- package/dist/core/application/timer/timer.js +19 -0
- package/dist/core/application/value-provider/value-provider.js +1 -0
- package/dist/core/infraestructure/db/bookmark.db.js +4 -0
- package/dist/core/infraestructure/event-handler/context/EventProvider.js +9 -0
- package/dist/core/infraestructure/event-handler/listener/event-listener-factory.js +8 -0
- package/dist/core/infraestructure/event-handler/useEventHadler.js +27 -0
- package/dist/core/infraestructure/initLayout/useLayoutEffectOnInit.js +4 -0
- package/dist/core/infraestructure/input-manager/useInputManager.js +14 -0
- package/dist/core/infraestructure/on-init/useEffectOnInit.js +9 -0
- package/dist/core/infraestructure/on-init-job/nativeOnInitJob.js +37 -0
- package/dist/core/infraestructure/on-init-job/nativeOnInitJobLazy.js +32 -0
- package/dist/core/infraestructure/pagination-manager/data-transforms/infinite.js +1 -0
- package/dist/core/infraestructure/pagination-manager/data-transforms/normal.js +1 -0
- package/dist/core/infraestructure/pagination-manager/usePaginationManager.js +59 -0
- package/dist/core/infraestructure/state/useRefStateProvider.js +39 -0
- package/dist/core/infraestructure/state/useStateProvider.js +35 -0
- package/dist/core/infraestructure/state-observer/useEffectStateObserver.js +16 -0
- package/dist/core/infraestructure/timer/sleep.js +2 -0
- package/dist/core/infraestructure/uuid/uuid.generator.js +2 -0
- package/dist/core/infraestructure/value-provider/useRefValueProvider.js +12 -0
- package/dist/core/utils/argument.type.js +1 -0
- package/dist/core/utils/optional.js +1 -0
- package/dist/file-display/FileDisplay.js +456 -0
- package/dist/file-display/components/Loading.js +4 -0
- package/dist/file-display/components/NodeDetails.js +50 -0
- package/dist/file-display/components/NodeList.js +61 -0
- package/dist/file-display/events/node.written.js +7 -0
- package/dist/file-display/hooks/useResize.js +24 -0
- package/dist/file-display/implementation/create.dir.js +7 -0
- package/dist/file-display/implementation/delete.js +9 -0
- package/dist/file-display/implementation/execute.command.async.js +6 -0
- package/dist/file-display/implementation/execute.command.sync.js +9 -0
- package/dist/file-display/implementation/execute.file.js +4 -0
- package/dist/file-display/implementation/filter.glob.js +4 -0
- package/dist/file-display/implementation/get.all.files.js +44 -0
- package/dist/file-display/implementation/get.directory.js +8 -0
- package/dist/file-display/implementation/get.upper.directory.js +17 -0
- package/dist/file-display/implementation/move.trash.js +9 -0
- package/dist/file-display/implementation/node.details.js +79 -0
- package/dist/file-display/implementation/paste.operation.js +40 -0
- package/dist/file-display/implementation/rename.js +6 -0
- package/dist/file-display/logic/file.manager.js +107 -0
- package/dist/file-display/logic/history.manager.js +47 -0
- package/dist/file-display/logic/node.detail.js +8 -0
- package/dist/file-display/logic/operations.manager.js +103 -0
- package/dist/file-display/services/create.dir.js +1 -0
- package/dist/file-display/services/delete.js +1 -0
- package/dist/file-display/services/execute.command.async.js +1 -0
- package/dist/file-display/services/execute.command.sync.js +1 -0
- package/dist/file-display/services/execute.file.js +1 -0
- package/dist/file-display/services/filter.glob.js +1 -0
- package/dist/file-display/services/get.all.files.js +1 -0
- package/dist/file-display/services/get.directory.js +1 -0
- package/dist/file-display/services/get.upper.directory.js +1 -0
- package/dist/file-display/services/move.trash.js +1 -0
- package/dist/file-display/services/node.details.js +1 -0
- package/dist/file-display/services/paste.operation.js +1 -0
- package/dist/file-display/services/remane.js +1 -0
- package/dist/file-display/types/node.details.js +1 -0
- package/dist/file-display/types/node.js +1 -0
- package/dist/file-display/utils/icon.parser.js +144 -0
- package/dist/input-capture/InputCapureWrapper.js +10 -0
- package/dist/input-capture/InputContextCapture.js +26 -0
- package/dist/tabs/TabsContext.js +17 -0
- package/dist/tabs/events/update.tab.data.js +8 -0
- package/dist/tabs/events/update.tab.selection.js +8 -0
- package/dist/tabs/logic/tabsManagerLogic.js +58 -0
- package/dist/tabs/wrapper/tabs.wrapper.js +38 -0
- package/dist/text-field/TextFieldCaptureContext.js +24 -0
- package/dist/text-field/TextFieldWrapper.js +21 -0
- package/package.json +62 -0
- package/readme.md +57 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
export const nativeOnInitJob = (stateFactory) => (callback, onTask) => {
|
2
|
+
const dataState = stateFactory(null);
|
3
|
+
const loadingState = stateFactory(false);
|
4
|
+
const errorState = stateFactory(null);
|
5
|
+
const doJob = async (...args) => {
|
6
|
+
if (loadingState.state)
|
7
|
+
throw new Error('Is in job');
|
8
|
+
dataState.setState(null);
|
9
|
+
errorState.setState(null);
|
10
|
+
loadingState.setState(true);
|
11
|
+
const loadingTask = onTask?.();
|
12
|
+
try {
|
13
|
+
const res = await callback(...args);
|
14
|
+
dataState.setState(res);
|
15
|
+
loadingState.setState(false);
|
16
|
+
loadingTask?.success?.();
|
17
|
+
return res;
|
18
|
+
}
|
19
|
+
catch (e) {
|
20
|
+
errorState.setState(e);
|
21
|
+
loadingTask?.error?.(e);
|
22
|
+
loadingState.setState(false);
|
23
|
+
throw e;
|
24
|
+
}
|
25
|
+
};
|
26
|
+
return {
|
27
|
+
do: doJob,
|
28
|
+
data: dataState.state,
|
29
|
+
error: errorState.state,
|
30
|
+
isLoading: loadingState.state,
|
31
|
+
};
|
32
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export const infiniteDataTransform = () => (res, prev) => [...prev, ...res];
|
@@ -0,0 +1 @@
|
|
1
|
+
export const normalDataTransform = () => (res, _prev) => res;
|
@@ -0,0 +1,59 @@
|
|
1
|
+
import { normalDataTransform } from './data-transforms/normal.js';
|
2
|
+
export const usePaginationManager = (stateFactory, stateObserver, onInit) => (callback, dataTransform = normalDataTransform()) => {
|
3
|
+
const pageState = stateFactory(1);
|
4
|
+
const dataState = stateFactory([]);
|
5
|
+
const errorState = stateFactory(null);
|
6
|
+
const loadingState = stateFactory(false);
|
7
|
+
const isTopState = stateFactory(false);
|
8
|
+
const job = async () => {
|
9
|
+
if (loadingState.state.value)
|
10
|
+
return;
|
11
|
+
loadingState.setState(true);
|
12
|
+
errorState.setState(null);
|
13
|
+
try {
|
14
|
+
const data = await callback(pageState.state.value);
|
15
|
+
if (data.length === 0)
|
16
|
+
isTopState.setState(true);
|
17
|
+
dataState.setState(dataTransform(data, dataState.state.value));
|
18
|
+
}
|
19
|
+
catch (e) {
|
20
|
+
errorState.setState(e);
|
21
|
+
}
|
22
|
+
loadingState.setState(false);
|
23
|
+
};
|
24
|
+
onInit(() => {
|
25
|
+
job();
|
26
|
+
});
|
27
|
+
stateObserver(() => {
|
28
|
+
job();
|
29
|
+
}, pageState.state);
|
30
|
+
const increment = () => pageState.setState(pageState.state.value + 1);
|
31
|
+
const reset = () => {
|
32
|
+
isTopState.setState(false);
|
33
|
+
dataState.setState([]);
|
34
|
+
pageState.setState(1);
|
35
|
+
job();
|
36
|
+
};
|
37
|
+
const previousPage = () => {
|
38
|
+
isTopState.setState(false);
|
39
|
+
if (pageState.state.value > 2)
|
40
|
+
pageState.setState(pageState.state.value - 1);
|
41
|
+
};
|
42
|
+
const setPage = (page) => {
|
43
|
+
isTopState.setState(false);
|
44
|
+
if (page < 1 || Math.ceil(page) !== page)
|
45
|
+
throw new Error('Invalid page');
|
46
|
+
pageState.setState(page);
|
47
|
+
};
|
48
|
+
return {
|
49
|
+
data: dataState.state,
|
50
|
+
error: errorState.state,
|
51
|
+
isLoading: loadingState.state,
|
52
|
+
increment,
|
53
|
+
reset,
|
54
|
+
page: pageState.state,
|
55
|
+
previousPage,
|
56
|
+
setPage,
|
57
|
+
isTop: isTopState.state,
|
58
|
+
};
|
59
|
+
};
|
@@ -0,0 +1,39 @@
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
2
|
+
export const useRefStateFactory = () => {
|
3
|
+
const [_, forceUpdate] = useState(0);
|
4
|
+
const isMounted = useRef(true);
|
5
|
+
useEffect(() => {
|
6
|
+
isMounted.current = true;
|
7
|
+
return () => {
|
8
|
+
isMounted.current = false;
|
9
|
+
};
|
10
|
+
}, []);
|
11
|
+
return (initialize) => {
|
12
|
+
const subscriptors = useRef([]);
|
13
|
+
const firstTime = useRef(true);
|
14
|
+
const state = useRef(initialize);
|
15
|
+
useEffect(() => {
|
16
|
+
if (firstTime.current) {
|
17
|
+
firstTime.current = false;
|
18
|
+
return;
|
19
|
+
}
|
20
|
+
subscriptors.current.forEach((e) => e(state.current));
|
21
|
+
}, [state]);
|
22
|
+
return {
|
23
|
+
state: {
|
24
|
+
get value() {
|
25
|
+
return state.current;
|
26
|
+
},
|
27
|
+
subscribe(callback) {
|
28
|
+
subscriptors.current.push(callback);
|
29
|
+
},
|
30
|
+
},
|
31
|
+
setState(value) {
|
32
|
+
if (!isMounted.current)
|
33
|
+
return;
|
34
|
+
state.current = value;
|
35
|
+
forceUpdate((value) => ++value);
|
36
|
+
},
|
37
|
+
};
|
38
|
+
};
|
39
|
+
};
|
@@ -0,0 +1,35 @@
|
|
1
|
+
import { useEffect, useRef, useState } from 'react';
|
2
|
+
export const useStateFactory = (initialize) => {
|
3
|
+
const subscriptors = useRef([]);
|
4
|
+
const firstTime = useRef(true);
|
5
|
+
const isMounted = useRef(true);
|
6
|
+
const [state, setState] = useState(initialize);
|
7
|
+
useEffect(() => {
|
8
|
+
if (firstTime.current) {
|
9
|
+
firstTime.current = false;
|
10
|
+
return;
|
11
|
+
}
|
12
|
+
subscriptors.current.forEach((e) => e(state));
|
13
|
+
}, [state]);
|
14
|
+
useEffect(() => {
|
15
|
+
isMounted.current = true;
|
16
|
+
return () => {
|
17
|
+
isMounted.current = false;
|
18
|
+
};
|
19
|
+
}, []);
|
20
|
+
return {
|
21
|
+
state: {
|
22
|
+
get value() {
|
23
|
+
return state;
|
24
|
+
},
|
25
|
+
subscribe(callback) {
|
26
|
+
subscriptors.current.push(callback);
|
27
|
+
},
|
28
|
+
},
|
29
|
+
setState(value) {
|
30
|
+
if (!isMounted.current)
|
31
|
+
return;
|
32
|
+
setState(value);
|
33
|
+
},
|
34
|
+
};
|
35
|
+
};
|
@@ -0,0 +1,16 @@
|
|
1
|
+
import { useEffect, useRef } from 'react';
|
2
|
+
export const useEffectStateObserver = (callback, ...states) => {
|
3
|
+
if (states.length === 0)
|
4
|
+
return;
|
5
|
+
const firstTime = useRef(true);
|
6
|
+
useEffect(() => {
|
7
|
+
if (firstTime.current) {
|
8
|
+
firstTime.current = false;
|
9
|
+
return;
|
10
|
+
}
|
11
|
+
const res = callback();
|
12
|
+
return () => {
|
13
|
+
res?.();
|
14
|
+
};
|
15
|
+
}, [...states.map((e) => e.value)]);
|
16
|
+
};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1 @@
|
|
1
|
+
export {};
|
@@ -0,0 +1,456 @@
|
|
1
|
+
import { existsSync } from 'node:fs';
|
2
|
+
import clipboardy from 'clipboardy';
|
3
|
+
import { Box, Text, useInput } from 'ink';
|
4
|
+
import React, { useContext, useRef, useState } from 'react';
|
5
|
+
import { AlertContext } from '../alerts/AlertContextProvider.js';
|
6
|
+
import { BookmarkPaneContext } from '../bookmark/context/BookmarkPaneContext.js';
|
7
|
+
import { createAddBookmarkItem } from '../bookmark/events/add.item.js';
|
8
|
+
import { ClipboardContext } from '../clipboard/ClipboardProvider.js';
|
9
|
+
import { EventContext } from '../core/infraestructure/event-handler/context/EventProvider.js';
|
10
|
+
import { nativeOnInitJob } from '../core/infraestructure/on-init-job/nativeOnInitJob.js';
|
11
|
+
import { useEffectOnInit } from '../core/infraestructure/on-init/useEffectOnInit.js';
|
12
|
+
import { useEffectStateObserver } from '../core/infraestructure/state-observer/useEffectStateObserver.js';
|
13
|
+
import { useRefStateFactory } from '../core/infraestructure/state/useRefStateProvider.js';
|
14
|
+
import { useRefValueProvider } from '../core/infraestructure/value-provider/useRefValueProvider.js';
|
15
|
+
import { InputContextCapture } from '../input-capture/InputContextCapture.js';
|
16
|
+
import { TabsContext } from '../tabs/TabsContext.js';
|
17
|
+
import { TextFieldContextCapture } from '../text-field/TextFieldCaptureContext.js';
|
18
|
+
import { NodeDetails } from './components/NodeDetails.js';
|
19
|
+
import { NodeList } from './components/NodeList.js';
|
20
|
+
import { createNodeWrittenEvent } from './events/node.written.js';
|
21
|
+
import { createDirectory } from './implementation/create.dir.js';
|
22
|
+
import { deleteNode } from './implementation/delete.js';
|
23
|
+
import { executeCommandAsync } from './implementation/execute.command.async.js';
|
24
|
+
import { executeCommandSync } from './implementation/execute.command.sync.js';
|
25
|
+
import { executeFile } from './implementation/execute.file.js';
|
26
|
+
import { filterByGlobPattern } from './implementation/filter.glob.js';
|
27
|
+
import { getAllFiles } from './implementation/get.all.files.js';
|
28
|
+
import { getNextDir } from './implementation/get.directory.js';
|
29
|
+
import { getUpperDirectory } from './implementation/get.upper.directory.js';
|
30
|
+
import { moveNodeToTrash } from './implementation/move.trash.js';
|
31
|
+
import { pasteOperation } from './implementation/paste.operation.js';
|
32
|
+
import { renameNode } from './implementation/rename.js';
|
33
|
+
import { fileManagerLogic } from './logic/file.manager.js';
|
34
|
+
import { historyManager } from './logic/history.manager.js';
|
35
|
+
import { operationsManager } from './logic/operations.manager.js';
|
36
|
+
export default function FileDisplay(props) {
|
37
|
+
const isInputEnable = useRef(true);
|
38
|
+
const stateFactory = useRefStateFactory();
|
39
|
+
const tabs = useContext(TabsContext);
|
40
|
+
const alert = useContext(AlertContext);
|
41
|
+
const inputCapture = useContext(InputContextCapture);
|
42
|
+
const [index, setIndex] = useState(-1);
|
43
|
+
const clipboard = useContext(ClipboardContext);
|
44
|
+
const textField = useContext(TextFieldContextCapture);
|
45
|
+
const eventHandler = useContext(EventContext);
|
46
|
+
const { isBookmarkEnabled } = useContext(BookmarkPaneContext);
|
47
|
+
const history = historyManager(useRefValueProvider(), eventHandler, props.initialData.history);
|
48
|
+
const files = fileManagerLogic(stateFactory, useEffectStateObserver, eventHandler, nativeOnInitJob(stateFactory, useEffectStateObserver, useEffectOnInit), props.initialData.path, getAllFiles, getUpperDirectory, getNextDir, executeFile, history, props.selection, filterByGlobPattern);
|
49
|
+
const operations = operationsManager(files, clipboard, pasteOperation, deleteNode, renameNode, createDirectory, executeCommandSync, executeCommandAsync, moveNodeToTrash);
|
50
|
+
const filesList = files.files.value ?? [];
|
51
|
+
const moveUpArrow = () => {
|
52
|
+
setIndex((prev) => {
|
53
|
+
if (prev <= -1)
|
54
|
+
return prev;
|
55
|
+
return prev - 1;
|
56
|
+
});
|
57
|
+
};
|
58
|
+
const moveDownArrow = () => {
|
59
|
+
setIndex((prev) => {
|
60
|
+
if (!filesList.length)
|
61
|
+
return -1;
|
62
|
+
if (prev + 1 >= filesList.length)
|
63
|
+
return filesList.length - 1;
|
64
|
+
return prev + 1;
|
65
|
+
});
|
66
|
+
};
|
67
|
+
const setCut = () => {
|
68
|
+
if (index < 0 || index >= filesList.length)
|
69
|
+
return;
|
70
|
+
if (filesList[index]?.type === 'DRIVE')
|
71
|
+
return;
|
72
|
+
operations.cut(filesList[index]);
|
73
|
+
alert.setAlert({
|
74
|
+
kind: 'INFO',
|
75
|
+
message: 'File added to clipboard to cut',
|
76
|
+
});
|
77
|
+
};
|
78
|
+
const setCopy = () => {
|
79
|
+
if (index < 0 || index >= filesList.length)
|
80
|
+
return;
|
81
|
+
if (filesList[index]?.type === 'DRIVE')
|
82
|
+
return;
|
83
|
+
operations.copy(filesList[index]);
|
84
|
+
alert.setAlert({
|
85
|
+
kind: 'INFO',
|
86
|
+
message: 'File added to clipboard to copy',
|
87
|
+
});
|
88
|
+
};
|
89
|
+
const executePaste = async (force) => {
|
90
|
+
if (!clipboard.item.value)
|
91
|
+
return;
|
92
|
+
isInputEnable.current = false;
|
93
|
+
alert.alertControlled({
|
94
|
+
kind: 'INFO',
|
95
|
+
message: clipboard.item.value.opeation === 'COPY'
|
96
|
+
? 'Coping item...'
|
97
|
+
: 'Cutting item...',
|
98
|
+
});
|
99
|
+
try {
|
100
|
+
await operations.paste(force);
|
101
|
+
alert.setAlert({
|
102
|
+
message: 'Paste successfull',
|
103
|
+
kind: 'SUCCESS',
|
104
|
+
});
|
105
|
+
eventHandler.publish(createNodeWrittenEvent());
|
106
|
+
}
|
107
|
+
catch (error) {
|
108
|
+
alert.setAlert({
|
109
|
+
kind: 'ERR',
|
110
|
+
message: error.message,
|
111
|
+
});
|
112
|
+
}
|
113
|
+
isInputEnable.current = true;
|
114
|
+
};
|
115
|
+
const openDirInNewTab = () => {
|
116
|
+
if (index < 0 || index >= filesList.length)
|
117
|
+
return;
|
118
|
+
const node = filesList[index];
|
119
|
+
if (node.type === 'FILE')
|
120
|
+
return;
|
121
|
+
tabs.addTab({
|
122
|
+
path: node.path,
|
123
|
+
history: {
|
124
|
+
forward: [],
|
125
|
+
previous: [],
|
126
|
+
},
|
127
|
+
});
|
128
|
+
};
|
129
|
+
const selectItem = () => {
|
130
|
+
if (index === -1)
|
131
|
+
files.gotToUpper();
|
132
|
+
else if (filesList[index])
|
133
|
+
files.selectNode(filesList[index]);
|
134
|
+
};
|
135
|
+
const deleteItem = () => {
|
136
|
+
if (index < 0 || index >= filesList.length)
|
137
|
+
return;
|
138
|
+
const node = filesList[index];
|
139
|
+
if (node.type === 'DRIVE')
|
140
|
+
return;
|
141
|
+
inputCapture.addCallback(async (key) => {
|
142
|
+
if (key !== 'Y')
|
143
|
+
return;
|
144
|
+
isInputEnable.current = false;
|
145
|
+
alert.alertControlled({
|
146
|
+
kind: 'INFO',
|
147
|
+
message: 'Deleting item...',
|
148
|
+
});
|
149
|
+
try {
|
150
|
+
await operations.removeNode(node);
|
151
|
+
alert.setAlert({
|
152
|
+
message: 'Delete successfull',
|
153
|
+
kind: 'SUCCESS',
|
154
|
+
});
|
155
|
+
eventHandler.publish(createNodeWrittenEvent());
|
156
|
+
}
|
157
|
+
catch (error) {
|
158
|
+
alert.setAlert({
|
159
|
+
kind: 'ERR',
|
160
|
+
message: error.message,
|
161
|
+
});
|
162
|
+
}
|
163
|
+
isInputEnable.current = true;
|
164
|
+
}, 'Do you want to remove this item? Y/n');
|
165
|
+
};
|
166
|
+
const createDir = () => {
|
167
|
+
if (filesList.some((e) => e.type === 'DRIVE'))
|
168
|
+
return;
|
169
|
+
textField.addCallback({
|
170
|
+
placeHolder: 'Set folder name',
|
171
|
+
callback: {
|
172
|
+
onSuccess: async (data) => {
|
173
|
+
if (!data)
|
174
|
+
return;
|
175
|
+
try {
|
176
|
+
await operations.createDirectory(data);
|
177
|
+
alert.setAlert({
|
178
|
+
message: 'Folder created',
|
179
|
+
kind: 'SUCCESS',
|
180
|
+
});
|
181
|
+
}
|
182
|
+
catch (error) {
|
183
|
+
alert.setAlert({
|
184
|
+
kind: 'ERR',
|
185
|
+
message: error.message,
|
186
|
+
});
|
187
|
+
}
|
188
|
+
},
|
189
|
+
onChange: (data) => {
|
190
|
+
if (!data ||
|
191
|
+
files.files.value?.some((e) => e.name === data))
|
192
|
+
textField.setError('Element already exist');
|
193
|
+
else
|
194
|
+
textField.setError('');
|
195
|
+
},
|
196
|
+
},
|
197
|
+
});
|
198
|
+
};
|
199
|
+
const renameItem = () => {
|
200
|
+
if (index < 0 || index >= filesList.length || selections.length)
|
201
|
+
return;
|
202
|
+
const node = filesList[index];
|
203
|
+
if (node.type === 'DRIVE')
|
204
|
+
return;
|
205
|
+
textField.addCallback({
|
206
|
+
placeHolder: 'Set item name',
|
207
|
+
defaultValue: node.name,
|
208
|
+
text: 'Rename item name',
|
209
|
+
callback: {
|
210
|
+
onSuccess: async (data) => {
|
211
|
+
if (!data)
|
212
|
+
return;
|
213
|
+
try {
|
214
|
+
await operations.rename(node, data);
|
215
|
+
alert.setAlert({
|
216
|
+
message: 'Item renamed',
|
217
|
+
kind: 'SUCCESS',
|
218
|
+
});
|
219
|
+
eventHandler.publish(createNodeWrittenEvent());
|
220
|
+
}
|
221
|
+
catch (error) {
|
222
|
+
alert.setAlert({
|
223
|
+
kind: 'ERR',
|
224
|
+
message: error.message,
|
225
|
+
});
|
226
|
+
}
|
227
|
+
},
|
228
|
+
onChange: (data) => {
|
229
|
+
if (!data ||
|
230
|
+
(data !== node.name &&
|
231
|
+
files.files.value?.some((e) => e.name === data)))
|
232
|
+
textField.setError('Element already exist');
|
233
|
+
else
|
234
|
+
textField.setError('');
|
235
|
+
},
|
236
|
+
},
|
237
|
+
});
|
238
|
+
};
|
239
|
+
const toggleSelectItem = () => {
|
240
|
+
if (index < 0 || index >= filesList.length)
|
241
|
+
return;
|
242
|
+
const node = filesList[index];
|
243
|
+
if (node.type === 'DRIVE')
|
244
|
+
return;
|
245
|
+
files.toggleSelected(node);
|
246
|
+
};
|
247
|
+
const selectToDetails = () => {
|
248
|
+
if (index < 0 || index >= filesList.length)
|
249
|
+
return;
|
250
|
+
const node = filesList[index];
|
251
|
+
files.selectNodeToDetails(node);
|
252
|
+
};
|
253
|
+
const addToBookmark = () => {
|
254
|
+
if (index < 0 || index >= filesList.length)
|
255
|
+
return;
|
256
|
+
const node = filesList[index];
|
257
|
+
if (node.type === 'FILE')
|
258
|
+
return;
|
259
|
+
eventHandler.publish(createAddBookmarkItem(node));
|
260
|
+
};
|
261
|
+
const copyNodePathToClipboard = () => {
|
262
|
+
if (index < 0 || index >= filesList.length)
|
263
|
+
return;
|
264
|
+
const node = filesList[index];
|
265
|
+
clipboardy.writeSync(node.path);
|
266
|
+
alert.setAlert({
|
267
|
+
kind: 'INFO',
|
268
|
+
message: 'Item path added to clipboard',
|
269
|
+
});
|
270
|
+
};
|
271
|
+
const copyPathToClipboard = () => {
|
272
|
+
clipboardy.writeSync(files.path.value);
|
273
|
+
alert.setAlert({
|
274
|
+
kind: 'INFO',
|
275
|
+
message: 'Current dir path added to clipboard',
|
276
|
+
});
|
277
|
+
};
|
278
|
+
const runCommandAsync = () => {
|
279
|
+
textField.addCallback({
|
280
|
+
placeHolder: 'Command in background...',
|
281
|
+
callback: {
|
282
|
+
onSuccess: async (command) => {
|
283
|
+
await operations.runCommandAsync(command);
|
284
|
+
},
|
285
|
+
onChange: async () => { },
|
286
|
+
},
|
287
|
+
});
|
288
|
+
};
|
289
|
+
const runCommandSync = () => {
|
290
|
+
textField.addCallback({
|
291
|
+
placeHolder: 'Command blocking...',
|
292
|
+
callback: {
|
293
|
+
onSuccess: async (command) => {
|
294
|
+
isInputEnable.current = false;
|
295
|
+
await operations
|
296
|
+
.runCommandSync(command)
|
297
|
+
.then((data) => alert.setAlert({
|
298
|
+
kind: 'INFO',
|
299
|
+
message: data,
|
300
|
+
}))
|
301
|
+
.catch((err) => alert.setAlert({
|
302
|
+
kind: 'ERR',
|
303
|
+
message: err.message,
|
304
|
+
}));
|
305
|
+
isInputEnable.current = true;
|
306
|
+
},
|
307
|
+
onChange: async () => { },
|
308
|
+
},
|
309
|
+
});
|
310
|
+
};
|
311
|
+
const setPath = () => {
|
312
|
+
textField.addCallback({
|
313
|
+
placeHolder: 'Set path',
|
314
|
+
defaultValue: files.path.value,
|
315
|
+
text: 'Navigate to path',
|
316
|
+
callback: {
|
317
|
+
onSuccess: async (data) => {
|
318
|
+
if (!data)
|
319
|
+
return;
|
320
|
+
files.navigateTo(data);
|
321
|
+
},
|
322
|
+
onChange: (data) => {
|
323
|
+
if (!existsSync(data))
|
324
|
+
textField.setError('Path not exist');
|
325
|
+
else
|
326
|
+
textField.setError('');
|
327
|
+
},
|
328
|
+
},
|
329
|
+
});
|
330
|
+
};
|
331
|
+
const moveItemToTrash = () => {
|
332
|
+
if (index < 0 || index >= filesList.length)
|
333
|
+
return;
|
334
|
+
const node = filesList[index];
|
335
|
+
if (node.type === 'DRIVE')
|
336
|
+
return;
|
337
|
+
inputCapture.addCallback(async (key) => {
|
338
|
+
if (key !== 'y')
|
339
|
+
return;
|
340
|
+
isInputEnable.current = false;
|
341
|
+
alert.alertControlled({
|
342
|
+
kind: 'INFO',
|
343
|
+
message: 'Moving item to trash...',
|
344
|
+
});
|
345
|
+
try {
|
346
|
+
await operations.removeNode(node);
|
347
|
+
alert.setAlert({
|
348
|
+
message: 'Moved successfull',
|
349
|
+
kind: 'SUCCESS',
|
350
|
+
});
|
351
|
+
eventHandler.publish(createNodeWrittenEvent());
|
352
|
+
}
|
353
|
+
catch (error) {
|
354
|
+
alert.setAlert({
|
355
|
+
kind: 'ERR',
|
356
|
+
message: error.message,
|
357
|
+
});
|
358
|
+
}
|
359
|
+
isInputEnable.current = true;
|
360
|
+
}, 'Do you want to move this item to trash? Y/n');
|
361
|
+
};
|
362
|
+
const setGlobPattern = () => {
|
363
|
+
if (filesList.some((e) => e.type === 'DRIVE'))
|
364
|
+
return;
|
365
|
+
textField.addCallback({
|
366
|
+
placeHolder: 'Add glob pattern to search...',
|
367
|
+
callback: {
|
368
|
+
onChange() { },
|
369
|
+
onSuccess(data) {
|
370
|
+
files.selectByGlobPattern(data);
|
371
|
+
},
|
372
|
+
},
|
373
|
+
});
|
374
|
+
};
|
375
|
+
useInput((input, key) => {
|
376
|
+
if (!isInputEnable.current ||
|
377
|
+
inputCapture.isInputEnabled ||
|
378
|
+
textField.isInputEnabled ||
|
379
|
+
isBookmarkEnabled)
|
380
|
+
return;
|
381
|
+
if (key.ctrl && key.upArrow)
|
382
|
+
files.gotToUpper();
|
383
|
+
else if (key.ctrl && key.leftArrow)
|
384
|
+
files.popHistory();
|
385
|
+
else if (key.ctrl && key.rightArrow)
|
386
|
+
files.forwardHistory();
|
387
|
+
else if (key.upArrow)
|
388
|
+
moveUpArrow();
|
389
|
+
else if (key.downArrow)
|
390
|
+
moveDownArrow();
|
391
|
+
else if (key.ctrl && input === 'd')
|
392
|
+
files.cleanNodeSelected();
|
393
|
+
else if (input === 'S' && key.shift)
|
394
|
+
addToBookmark();
|
395
|
+
else if (input === 'i')
|
396
|
+
selectToDetails();
|
397
|
+
else if (input === 'a')
|
398
|
+
createDir();
|
399
|
+
else if (input === 'l' && key.ctrl)
|
400
|
+
setPath();
|
401
|
+
else if (input === 'R' && key.shift)
|
402
|
+
renameItem();
|
403
|
+
else if (input === 'd')
|
404
|
+
moveItemToTrash();
|
405
|
+
else if (input === 'D' && key.shift)
|
406
|
+
deleteItem();
|
407
|
+
else if (input === 'p')
|
408
|
+
executePaste(false);
|
409
|
+
else if (input === 'P' && key.shift)
|
410
|
+
executePaste(true);
|
411
|
+
else if (key.shift && input === 'T')
|
412
|
+
openDirInNewTab();
|
413
|
+
else if (input === 'C' && key.shift)
|
414
|
+
setCut();
|
415
|
+
else if (input === 'c')
|
416
|
+
setCopy();
|
417
|
+
else if (input === 'r')
|
418
|
+
files.refresh();
|
419
|
+
else if (key.shift && key.rightArrow)
|
420
|
+
files.unSelectAll();
|
421
|
+
else if (key.rightArrow)
|
422
|
+
toggleSelectItem();
|
423
|
+
else if (key.shift && input === 'A')
|
424
|
+
files.selectAll();
|
425
|
+
else if (key.shift && input === 'I')
|
426
|
+
files.inevertSelection();
|
427
|
+
else if (key.return)
|
428
|
+
selectItem();
|
429
|
+
else if (key.escape)
|
430
|
+
clipboard.removeItem();
|
431
|
+
else if (input === ';')
|
432
|
+
runCommandAsync();
|
433
|
+
else if (input === ':')
|
434
|
+
runCommandSync();
|
435
|
+
else if (input === 'y')
|
436
|
+
copyNodePathToClipboard();
|
437
|
+
else if (input === 'Y' && key.shift)
|
438
|
+
copyPathToClipboard();
|
439
|
+
else if (input === 'g')
|
440
|
+
setGlobPattern();
|
441
|
+
});
|
442
|
+
if (files.isLoading.value)
|
443
|
+
return (React.createElement(Box, { width: "100%", alignItems: "center" },
|
444
|
+
React.createElement(Text, null, "Loading...")));
|
445
|
+
if (files.isError.value)
|
446
|
+
return (React.createElement(Box, { width: "100%", alignItems: "center" },
|
447
|
+
React.createElement(Text, null, files.isError.value.message)));
|
448
|
+
const selections = files.selections.value;
|
449
|
+
return (React.createElement(React.Fragment, null,
|
450
|
+
React.createElement(Box, { height: "100%", flexDirection: "row", borderStyle: "round" },
|
451
|
+
React.createElement(Box, { overflowY: "hidden", flexDirection: "column", width: "100%", height: "100%" },
|
452
|
+
React.createElement(Box, { width: "100%", borderStyle: "double" },
|
453
|
+
React.createElement(Text, null, files.path.value)),
|
454
|
+
React.createElement(NodeList, { nodes: files.files.value, index: index, isTabs: tabs.tabs.value.length > 1, selections: files.selections.value })),
|
455
|
+
files.selectedNode.value && (React.createElement(NodeDetails, { node: files.selectedNode.value })))));
|
456
|
+
}
|