@danixl30/file-explorer-cli 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (110) hide show
  1. package/LICENSE +21 -0
  2. package/dist/alerts/AlertContextProvider.js +13 -0
  3. package/dist/alerts/components/AlertDisplay.js +19 -0
  4. package/dist/alerts/logic/alert.logic.js +16 -0
  5. package/dist/app.js +27 -0
  6. package/dist/bookmark/Bookmark.js +123 -0
  7. package/dist/bookmark/components/BookmarkList.js +47 -0
  8. package/dist/bookmark/context/BookmarkPaneContext.js +9 -0
  9. package/dist/bookmark/events/add.item.js +8 -0
  10. package/dist/bookmark/implementations/clean.bookmarks.js +6 -0
  11. package/dist/bookmark/implementations/get.all.bookmarks.js +2 -0
  12. package/dist/bookmark/implementations/save.bookmarks.js +5 -0
  13. package/dist/bookmark/logic/bookmark.manager.js +25 -0
  14. package/dist/bookmark/services/clean.bookmarks.js +1 -0
  15. package/dist/bookmark/services/get.all.bookmarks.js +1 -0
  16. package/dist/bookmark/services/write.bookmarks.js +1 -0
  17. package/dist/bookmark/types/bookmark.js +1 -0
  18. package/dist/cli.js +31 -0
  19. package/dist/clipboard/ClipboardProvider.js +8 -0
  20. package/dist/clipboard/logic/clipboard-logic.js +10 -0
  21. package/dist/core/application/event-handler/event-handler.js +1 -0
  22. package/dist/core/application/event-handler/listener/event-listener.js +1 -0
  23. package/dist/core/application/event-handler/types/event.js +1 -0
  24. package/dist/core/application/event-handler/types/subscription.js +1 -0
  25. package/dist/core/application/id-generator/id.generator.js +1 -0
  26. package/dist/core/application/init-layout/init-layout.js +1 -0
  27. package/dist/core/application/input-manager/input-manager.js +1 -0
  28. package/dist/core/application/input-manager/types/input-manager-result.js +1 -0
  29. package/dist/core/application/on-init/on-init.js +1 -0
  30. package/dist/core/application/on-init-job/lazy/on-init-job-lazy.js +1 -0
  31. package/dist/core/application/on-init-job/on-init-job.js +1 -0
  32. package/dist/core/application/pagination-manager/pagination-manager.js +1 -0
  33. package/dist/core/application/pagination-manager/types/pagination-result.js +1 -0
  34. package/dist/core/application/service/application-service.js +1 -0
  35. package/dist/core/application/state/state-factory.js +1 -0
  36. package/dist/core/application/state/state-provider.js +1 -0
  37. package/dist/core/application/state-observers/state-observer.js +1 -0
  38. package/dist/core/application/timer/sleep/sleep.js +1 -0
  39. package/dist/core/application/timer/timer.js +19 -0
  40. package/dist/core/application/value-provider/value-provider.js +1 -0
  41. package/dist/core/infraestructure/db/bookmark.db.js +4 -0
  42. package/dist/core/infraestructure/event-handler/context/EventProvider.js +9 -0
  43. package/dist/core/infraestructure/event-handler/listener/event-listener-factory.js +8 -0
  44. package/dist/core/infraestructure/event-handler/useEventHadler.js +27 -0
  45. package/dist/core/infraestructure/initLayout/useLayoutEffectOnInit.js +4 -0
  46. package/dist/core/infraestructure/input-manager/useInputManager.js +14 -0
  47. package/dist/core/infraestructure/on-init/useEffectOnInit.js +9 -0
  48. package/dist/core/infraestructure/on-init-job/nativeOnInitJob.js +37 -0
  49. package/dist/core/infraestructure/on-init-job/nativeOnInitJobLazy.js +32 -0
  50. package/dist/core/infraestructure/pagination-manager/data-transforms/infinite.js +1 -0
  51. package/dist/core/infraestructure/pagination-manager/data-transforms/normal.js +1 -0
  52. package/dist/core/infraestructure/pagination-manager/usePaginationManager.js +59 -0
  53. package/dist/core/infraestructure/state/useRefStateProvider.js +39 -0
  54. package/dist/core/infraestructure/state/useStateProvider.js +35 -0
  55. package/dist/core/infraestructure/state-observer/useEffectStateObserver.js +16 -0
  56. package/dist/core/infraestructure/timer/sleep.js +2 -0
  57. package/dist/core/infraestructure/uuid/uuid.generator.js +2 -0
  58. package/dist/core/infraestructure/value-provider/useRefValueProvider.js +12 -0
  59. package/dist/core/utils/argument.type.js +1 -0
  60. package/dist/core/utils/optional.js +1 -0
  61. package/dist/file-display/FileDisplay.js +456 -0
  62. package/dist/file-display/components/Loading.js +4 -0
  63. package/dist/file-display/components/NodeDetails.js +50 -0
  64. package/dist/file-display/components/NodeList.js +61 -0
  65. package/dist/file-display/events/node.written.js +7 -0
  66. package/dist/file-display/hooks/useResize.js +24 -0
  67. package/dist/file-display/implementation/create.dir.js +7 -0
  68. package/dist/file-display/implementation/delete.js +9 -0
  69. package/dist/file-display/implementation/execute.command.async.js +6 -0
  70. package/dist/file-display/implementation/execute.command.sync.js +9 -0
  71. package/dist/file-display/implementation/execute.file.js +4 -0
  72. package/dist/file-display/implementation/filter.glob.js +4 -0
  73. package/dist/file-display/implementation/get.all.files.js +44 -0
  74. package/dist/file-display/implementation/get.directory.js +8 -0
  75. package/dist/file-display/implementation/get.upper.directory.js +17 -0
  76. package/dist/file-display/implementation/move.trash.js +9 -0
  77. package/dist/file-display/implementation/node.details.js +79 -0
  78. package/dist/file-display/implementation/paste.operation.js +40 -0
  79. package/dist/file-display/implementation/rename.js +6 -0
  80. package/dist/file-display/logic/file.manager.js +107 -0
  81. package/dist/file-display/logic/history.manager.js +47 -0
  82. package/dist/file-display/logic/node.detail.js +8 -0
  83. package/dist/file-display/logic/operations.manager.js +103 -0
  84. package/dist/file-display/services/create.dir.js +1 -0
  85. package/dist/file-display/services/delete.js +1 -0
  86. package/dist/file-display/services/execute.command.async.js +1 -0
  87. package/dist/file-display/services/execute.command.sync.js +1 -0
  88. package/dist/file-display/services/execute.file.js +1 -0
  89. package/dist/file-display/services/filter.glob.js +1 -0
  90. package/dist/file-display/services/get.all.files.js +1 -0
  91. package/dist/file-display/services/get.directory.js +1 -0
  92. package/dist/file-display/services/get.upper.directory.js +1 -0
  93. package/dist/file-display/services/move.trash.js +1 -0
  94. package/dist/file-display/services/node.details.js +1 -0
  95. package/dist/file-display/services/paste.operation.js +1 -0
  96. package/dist/file-display/services/remane.js +1 -0
  97. package/dist/file-display/types/node.details.js +1 -0
  98. package/dist/file-display/types/node.js +1 -0
  99. package/dist/file-display/utils/icon.parser.js +144 -0
  100. package/dist/input-capture/InputCapureWrapper.js +10 -0
  101. package/dist/input-capture/InputContextCapture.js +26 -0
  102. package/dist/tabs/TabsContext.js +17 -0
  103. package/dist/tabs/events/update.tab.data.js +8 -0
  104. package/dist/tabs/events/update.tab.selection.js +8 -0
  105. package/dist/tabs/logic/tabsManagerLogic.js +58 -0
  106. package/dist/tabs/wrapper/tabs.wrapper.js +38 -0
  107. package/dist/text-field/TextFieldCaptureContext.js +24 -0
  108. package/dist/text-field/TextFieldWrapper.js +21 -0
  109. package/package.json +62 -0
  110. 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,2 @@
1
+ import { setTimeout } from 'node:timers/promises';
2
+ export const setTimeoutSleep = (time) => setTimeout(time);
@@ -0,0 +1,2 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ export const uuidGenerator = () => randomUUID();
@@ -0,0 +1,12 @@
1
+ import { useRef } from 'react';
2
+ export const useRefValueProvider = () => (initialValue) => {
3
+ const ref = useRef(initialValue);
4
+ return {
5
+ get value() {
6
+ return ref.current;
7
+ },
8
+ set value(value) {
9
+ ref.current = value;
10
+ },
11
+ };
12
+ };
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ import React from 'react';
2
+ export const Loading = (props) => {
3
+ return React.createElement(React.Fragment, null, props.isloading ? props.fallback : props.children);
4
+ };