vzcode 1.14.0 → 1.16.0
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/assets/{index-Wxh-Jaj6.css → index-B6yTvvah.css} +1 -1
- package/dist/assets/index-BlwLvENZ.js +159 -0
- package/dist/index.html +2 -2
- package/package.json +7 -7
- package/src/client/AIAssist/AIAssistWidget/index.tsx +10 -6
- package/src/client/CodeEditor/index.tsx +4 -4
- package/src/client/CodeEditor/json1PresenceDisplay.ts +5 -5
- package/src/client/TabList/index.tsx +8 -11
- package/src/client/VZCodeContext.tsx +29 -11
- package/src/client/VZMiddle.tsx +81 -27
- package/src/client/VZResizer/index.tsx +3 -3
- package/src/client/VZSidebar/FileListing.tsx +33 -55
- package/src/client/VZSidebar/FileTypeIcon.tsx +49 -0
- package/src/client/VZSidebar/Item.tsx +5 -9
- package/src/client/VZSidebar/Listing.tsx +2 -2
- package/src/client/VZSidebar/Search.tsx +412 -108
- package/src/client/VZSidebar/index.tsx +1 -1
- package/src/client/VZSidebar/styles.scss +36 -22
- package/src/client/presenceColor.ts +8 -0
- package/src/client/useActions.ts +31 -0
- package/src/client/useKeyboardShortcuts.ts +13 -3
- package/src/client/vzReducer/createInitialState.ts +7 -1
- package/src/client/vzReducer/index.ts +21 -0
- package/src/client/vzReducer/openTabReducer.ts +4 -3
- package/src/client/vzReducer/searchReducer.ts +46 -1
- package/src/types.ts +2 -0
- package/dist/assets/index-DGNI0PAo.js +0 -157
package/dist/index.html
CHANGED
|
@@ -20,8 +20,8 @@
|
|
|
20
20
|
href="https://fonts.googleapis.com/css2?family=Poppins:wght@300;400;500;600;700&display=swap"
|
|
21
21
|
rel="stylesheet"
|
|
22
22
|
/>
|
|
23
|
-
<script type="module" crossorigin src="/assets/index-
|
|
24
|
-
<link rel="stylesheet" crossorigin href="/assets/index-
|
|
23
|
+
<script type="module" crossorigin src="/assets/index-BlwLvENZ.js"></script>
|
|
24
|
+
<link rel="stylesheet" crossorigin href="/assets/index-B6yTvvah.css">
|
|
25
25
|
</head>
|
|
26
26
|
<body>
|
|
27
27
|
<div id="root"></div>
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vzcode",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.16.0",
|
|
4
4
|
"description": "Multiplayer code editor system",
|
|
5
5
|
"main": "src/index.ts",
|
|
6
6
|
"type": "module",
|
|
@@ -103,7 +103,7 @@
|
|
|
103
103
|
},
|
|
104
104
|
"homepage": "https://github.com/vizhub-core/vzcode#readme",
|
|
105
105
|
"dependencies": {
|
|
106
|
-
"@codemirror/autocomplete": "^6.
|
|
106
|
+
"@codemirror/autocomplete": "^6.18.0",
|
|
107
107
|
"@codemirror/lang-css": "^6.2.1",
|
|
108
108
|
"@codemirror/lang-html": "^6.4.9",
|
|
109
109
|
"@codemirror/lang-javascript": "^6.2.2",
|
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"@codemirror/lang-markdown": "^6.2.5",
|
|
112
112
|
"@codemirror/state": "^6.4.1",
|
|
113
113
|
"@codemirror/theme-one-dark": "^6.1.2",
|
|
114
|
-
"@codemirror/view": "^6.
|
|
114
|
+
"@codemirror/view": "^6.30.0",
|
|
115
115
|
"@lezer/highlight": "^1.2.0",
|
|
116
116
|
"@replit/codemirror-indentation-markers": "^6.5.3",
|
|
117
117
|
"@replit/codemirror-interact": "^6.3.1",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
"json0-ot-diff": "^1.1.2",
|
|
141
141
|
"ngrok": "^4.3.3",
|
|
142
142
|
"open": "^10.1.0",
|
|
143
|
-
"openai": "^4.
|
|
143
|
+
"openai": "^4.55.4",
|
|
144
144
|
"prettier-plugin-svelte": "^3.2.6",
|
|
145
145
|
"react": "^18.3.1",
|
|
146
146
|
"react-bootstrap": "^2.10.4",
|
|
@@ -160,11 +160,11 @@
|
|
|
160
160
|
"prettier": "^3.3.3",
|
|
161
161
|
"sass": "^1.77.8",
|
|
162
162
|
"typescript": "^5.5.4",
|
|
163
|
-
"vite": "^5.
|
|
163
|
+
"vite": "^5.4.0",
|
|
164
164
|
"vitest": "^2.0.5"
|
|
165
165
|
},
|
|
166
166
|
"optionalDependencies": {
|
|
167
|
-
"@rollup/rollup-darwin-arm64": "^4.
|
|
168
|
-
"@rollup/rollup-win32-x64-msvc": "^4.
|
|
167
|
+
"@rollup/rollup-darwin-arm64": "^4.20.0",
|
|
168
|
+
"@rollup/rollup-win32-x64-msvc": "^4.20.0"
|
|
169
169
|
}
|
|
170
170
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { useCallback, useContext, useState } from 'react';
|
|
2
2
|
import { OverlayTrigger, Tooltip } from '../../bootstrap';
|
|
3
|
+
import { FileId, PaneId, TabState } from '../../../types';
|
|
3
4
|
import { VZCodeContext } from '../../VZCodeContext';
|
|
4
5
|
import {
|
|
5
6
|
RequestId,
|
|
@@ -7,8 +8,8 @@ import {
|
|
|
7
8
|
} from '../../generateRequestId';
|
|
8
9
|
import { SparklesSVG } from '../../Icons';
|
|
9
10
|
import { startAIAssist } from '../startAIAssist';
|
|
10
|
-
import { Spinner } from '../Spinner';
|
|
11
11
|
import { editorCacheKey } from '../../useEditorCache';
|
|
12
|
+
import { Spinner } from '../Spinner';
|
|
12
13
|
import './style.scss';
|
|
13
14
|
|
|
14
15
|
const enableStopGeneration = false;
|
|
@@ -18,17 +19,20 @@ export const AIAssistWidget = ({
|
|
|
18
19
|
aiAssistOptions,
|
|
19
20
|
aiAssistTooltipText = 'Start AI Assist',
|
|
20
21
|
aiAssistClickOverride,
|
|
22
|
+
activeFileId,
|
|
23
|
+
tabList,
|
|
24
|
+
paneId,
|
|
21
25
|
}: {
|
|
22
26
|
aiAssistEndpoint: string;
|
|
23
27
|
aiAssistOptions: { [key: string]: string };
|
|
24
28
|
aiAssistTooltipText?: string;
|
|
25
29
|
aiAssistClickOverride?: () => void;
|
|
30
|
+
activeFileId: FileId;
|
|
31
|
+
tabList: Array<TabState>;
|
|
32
|
+
paneId: PaneId;
|
|
26
33
|
}) => {
|
|
27
34
|
const {
|
|
28
35
|
shareDBDoc,
|
|
29
|
-
activeFileId,
|
|
30
|
-
activePaneId,
|
|
31
|
-
tabList,
|
|
32
36
|
editorCache,
|
|
33
37
|
runPrettierRef,
|
|
34
38
|
runCodeRef,
|
|
@@ -52,7 +56,7 @@ export const AIAssistWidget = ({
|
|
|
52
56
|
// Wait for generation to finish.
|
|
53
57
|
await startAIAssist({
|
|
54
58
|
view: editorCache.get(
|
|
55
|
-
editorCacheKey(activeFileId,
|
|
59
|
+
editorCacheKey(activeFileId, paneId),
|
|
56
60
|
).editor,
|
|
57
61
|
shareDBDoc,
|
|
58
62
|
fileId: activeFileId,
|
|
@@ -96,7 +100,7 @@ export const AIAssistWidget = ({
|
|
|
96
100
|
: currentAIStreamId,
|
|
97
101
|
);
|
|
98
102
|
}
|
|
99
|
-
}, [activeFileId,
|
|
103
|
+
}, [activeFileId, paneId, aiStreamId]);
|
|
100
104
|
|
|
101
105
|
const showWidget = enableStopGeneration
|
|
102
106
|
? true
|
|
@@ -24,7 +24,7 @@ export const CodeEditor = ({
|
|
|
24
24
|
allowGlobals: boolean;
|
|
25
25
|
}) => {
|
|
26
26
|
const {
|
|
27
|
-
|
|
27
|
+
activePane,
|
|
28
28
|
shareDBDoc,
|
|
29
29
|
content,
|
|
30
30
|
submitOperation,
|
|
@@ -84,7 +84,7 @@ export const CodeEditor = ({
|
|
|
84
84
|
const editorCacheValue: EditorCacheValue = useMemo(
|
|
85
85
|
() =>
|
|
86
86
|
getOrCreateEditor({
|
|
87
|
-
fileId: activeFileId,
|
|
87
|
+
fileId: activePane.activeFileId,
|
|
88
88
|
shareDBDoc,
|
|
89
89
|
content,
|
|
90
90
|
filesPath,
|
|
@@ -102,7 +102,7 @@ export const CodeEditor = ({
|
|
|
102
102
|
// splitPaneView,
|
|
103
103
|
}),
|
|
104
104
|
[
|
|
105
|
-
|
|
105
|
+
activePane,
|
|
106
106
|
shareDBDoc,
|
|
107
107
|
filesPath,
|
|
108
108
|
localPresence,
|
|
@@ -144,7 +144,7 @@ export const CodeEditor = ({
|
|
|
144
144
|
}, [shareDBDoc, editorCacheValue]);
|
|
145
145
|
|
|
146
146
|
// Focus the editor
|
|
147
|
-
|
|
147
|
+
useEffect(() => {
|
|
148
148
|
if (editorWantsFocus) {
|
|
149
149
|
editorCacheValue.editor.focus();
|
|
150
150
|
editorNoLongerWantsFocus();
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
Decoration,
|
|
6
6
|
} from '@codemirror/view';
|
|
7
7
|
import { Annotation, RangeSet } from '@codemirror/state';
|
|
8
|
-
import
|
|
8
|
+
import { assignUserColor } from '../presenceColor';
|
|
9
9
|
import {
|
|
10
10
|
FileId,
|
|
11
11
|
Presence,
|
|
@@ -114,11 +114,11 @@ export const json1PresenceDisplay = ({
|
|
|
114
114
|
const { start, end } = presence;
|
|
115
115
|
const from = +start[start.length - 1];
|
|
116
116
|
const to = +end[end.length - 1];
|
|
117
|
-
const userColor =
|
|
118
|
-
|
|
119
|
-
|
|
117
|
+
const userColor = assignUserColor(
|
|
118
|
+
presence.username,
|
|
119
|
+
);
|
|
120
120
|
const { username } = presence;
|
|
121
|
-
|
|
121
|
+
//console.log("File User Color:" + assignUserColor(presence.username));
|
|
122
122
|
presenceDecorations.push({
|
|
123
123
|
from,
|
|
124
124
|
to: from,
|
|
@@ -1,26 +1,23 @@
|
|
|
1
1
|
import { useContext } from 'react';
|
|
2
|
+
import { TabState } from '../../types';
|
|
2
3
|
import { VZCodeContext } from '../VZCodeContext';
|
|
3
4
|
import { Tab } from './Tab';
|
|
4
5
|
import './style.scss';
|
|
5
|
-
import { TabState } from '../../types';
|
|
6
6
|
|
|
7
7
|
// Displays the list of tabs above the code editor.
|
|
8
|
-
export const TabList = () => {
|
|
9
|
-
const {
|
|
10
|
-
|
|
11
|
-
activeFileId,
|
|
12
|
-
setActiveFileId,
|
|
13
|
-
tabList,
|
|
14
|
-
openTab,
|
|
15
|
-
closeTabs,
|
|
16
|
-
} = useContext(VZCodeContext);
|
|
8
|
+
export const TabList = ({ activeFileId, tabList }) => {
|
|
9
|
+
const { files, setActiveFileId, openTab, closeTabs } =
|
|
10
|
+
useContext(VZCodeContext);
|
|
17
11
|
|
|
18
12
|
return (
|
|
19
13
|
<div className="vz-tab-list">
|
|
20
14
|
{files &&
|
|
21
15
|
tabList
|
|
22
16
|
// Handles the case that the tab list references a file that was deleted.
|
|
23
|
-
.filter(
|
|
17
|
+
.filter(
|
|
18
|
+
(tabState: TabState) =>
|
|
19
|
+
tabState.fileId in files,
|
|
20
|
+
)
|
|
24
21
|
.map((tabState: TabState) => (
|
|
25
22
|
<Tab
|
|
26
23
|
key={tabState.fileId}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
PresenceIndicator,
|
|
19
19
|
Pane,
|
|
20
20
|
PaneId,
|
|
21
|
+
LeafPane,
|
|
21
22
|
} from '../types';
|
|
22
23
|
import { usePrettier } from './usePrettier';
|
|
23
24
|
import { useTypeScript } from './useTypeScript';
|
|
@@ -37,6 +38,7 @@ import {
|
|
|
37
38
|
import { useURLSync } from './useURLSync';
|
|
38
39
|
import { useKeyboardShortcuts } from './useKeyboardShortcuts';
|
|
39
40
|
import { useRunCode } from './useRunCode';
|
|
41
|
+
import { findPane } from './vzReducer/findPane';
|
|
40
42
|
|
|
41
43
|
// This context centralizes all the "smart" logic
|
|
42
44
|
// to do with the application state. This includes
|
|
@@ -72,14 +74,14 @@ export type VZCodeContextValue = {
|
|
|
72
74
|
) => void;
|
|
73
75
|
deleteDirectory: (directoryId: string) => void;
|
|
74
76
|
|
|
75
|
-
activeFileId: string | null;
|
|
76
77
|
setActiveFileId: (fileId: string | null) => void;
|
|
77
78
|
setActiveFileLeft: () => void;
|
|
78
79
|
setActiveFileRight: () => void;
|
|
79
80
|
|
|
80
81
|
activePaneId: PaneId;
|
|
82
|
+
pane: Pane;
|
|
83
|
+
activePane: LeafPane;
|
|
81
84
|
|
|
82
|
-
tabList: Array<TabState>;
|
|
83
85
|
openTab: (tabState: TabState) => void;
|
|
84
86
|
closeTabs: (fileIds: string[]) => void;
|
|
85
87
|
|
|
@@ -123,6 +125,15 @@ export type VZCodeContextValue = {
|
|
|
123
125
|
id: string,
|
|
124
126
|
visibility: SearchFileVisibility,
|
|
125
127
|
) => void;
|
|
128
|
+
setSearchLineVisibility: (
|
|
129
|
+
files: ShareDBDoc<VZCodeContent>,
|
|
130
|
+
id: string,
|
|
131
|
+
line: number,
|
|
132
|
+
) => void;
|
|
133
|
+
setSearchFocusedIndex: (
|
|
134
|
+
focusedIndex: number,
|
|
135
|
+
childIndex: number,
|
|
136
|
+
) => void;
|
|
126
137
|
toggleSearchFocused: () => void;
|
|
127
138
|
|
|
128
139
|
isCreateFileModalOpen: boolean;
|
|
@@ -251,12 +262,11 @@ export const VZCodeProvider = ({
|
|
|
251
262
|
sidebarPresenceIndicators,
|
|
252
263
|
} = state;
|
|
253
264
|
|
|
254
|
-
|
|
255
|
-
if (
|
|
265
|
+
const activePane = findPane(pane, activePaneId);
|
|
266
|
+
if (activePane.type !== 'leafPane') {
|
|
267
|
+
// Should never happen
|
|
256
268
|
throw new Error('Expected leafPane');
|
|
257
269
|
}
|
|
258
|
-
const tabList = pane.tabList;
|
|
259
|
-
const activeFileId = pane.activeFileId;
|
|
260
270
|
|
|
261
271
|
// Functions for dispatching actions to the reducer.
|
|
262
272
|
const {
|
|
@@ -270,6 +280,8 @@ export const VZCodeProvider = ({
|
|
|
270
280
|
setSearch,
|
|
271
281
|
setSearchResults,
|
|
272
282
|
setSearchFileVisibility,
|
|
283
|
+
setSearchLineVisibility,
|
|
284
|
+
setSearchFocusedIndex,
|
|
273
285
|
toggleSearchFocused,
|
|
274
286
|
setIsSettingsOpen,
|
|
275
287
|
setIsDocOpen,
|
|
@@ -287,8 +299,8 @@ export const VZCodeProvider = ({
|
|
|
287
299
|
content,
|
|
288
300
|
openTab,
|
|
289
301
|
setActiveFileId,
|
|
290
|
-
tabList,
|
|
291
|
-
activeFileId,
|
|
302
|
+
tabList: activePane.tabList,
|
|
303
|
+
activeFileId: activePane.activeFileId,
|
|
292
304
|
});
|
|
293
305
|
|
|
294
306
|
// The set of open directories.
|
|
@@ -363,7 +375,9 @@ export const VZCodeProvider = ({
|
|
|
363
375
|
|
|
364
376
|
useKeyboardShortcuts({
|
|
365
377
|
closeTabs,
|
|
366
|
-
|
|
378
|
+
// TODO verify that this makes sense
|
|
379
|
+
activeFileId: activePane.activeFileId,
|
|
380
|
+
activePaneId,
|
|
367
381
|
handleOpenCreateFileModal,
|
|
368
382
|
setActiveFileLeft,
|
|
369
383
|
setActiveFileRight,
|
|
@@ -395,14 +409,16 @@ export const VZCodeProvider = ({
|
|
|
395
409
|
renameDirectory,
|
|
396
410
|
deleteDirectory,
|
|
397
411
|
|
|
398
|
-
activeFileId,
|
|
399
412
|
setActiveFileId,
|
|
400
413
|
setActiveFileLeft,
|
|
401
414
|
setActiveFileRight,
|
|
402
415
|
|
|
403
416
|
activePaneId,
|
|
417
|
+
// Root pane
|
|
418
|
+
pane,
|
|
419
|
+
// Active leaf pane
|
|
420
|
+
activePane,
|
|
404
421
|
|
|
405
|
-
tabList,
|
|
406
422
|
openTab,
|
|
407
423
|
closeTabs,
|
|
408
424
|
|
|
@@ -412,6 +428,8 @@ export const VZCodeProvider = ({
|
|
|
412
428
|
setSearch,
|
|
413
429
|
setSearchResults,
|
|
414
430
|
setSearchFileVisibility,
|
|
431
|
+
setSearchLineVisibility,
|
|
432
|
+
setSearchFocusedIndex,
|
|
415
433
|
toggleSearchFocused,
|
|
416
434
|
|
|
417
435
|
isSettingsOpen,
|
package/src/client/VZMiddle.tsx
CHANGED
|
@@ -9,6 +9,67 @@ import { VZCodeContext } from './VZCodeContext';
|
|
|
9
9
|
import { RunCodeWidget } from './RunCodeWidget';
|
|
10
10
|
import { InteractRule } from '@replit/codemirror-interact';
|
|
11
11
|
|
|
12
|
+
// TODO modify this to handle the SplitPane type
|
|
13
|
+
// Recursive structure?
|
|
14
|
+
// SplitPaneView
|
|
15
|
+
// LeafPaneView
|
|
16
|
+
const PaneView = ({
|
|
17
|
+
pane,
|
|
18
|
+
content,
|
|
19
|
+
customInteractRules,
|
|
20
|
+
allowGlobals,
|
|
21
|
+
enableAIAssist,
|
|
22
|
+
aiAssistEndpoint,
|
|
23
|
+
aiAssistOptions,
|
|
24
|
+
aiAssistTooltipText,
|
|
25
|
+
aiAssistClickOverride,
|
|
26
|
+
}) => {
|
|
27
|
+
// This prevents the CodeEditor from rendering
|
|
28
|
+
// during SSR.
|
|
29
|
+
const [isClient, setIsClient] = useState(false);
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
setIsClient(true);
|
|
32
|
+
}, []);
|
|
33
|
+
|
|
34
|
+
// TODO something like
|
|
35
|
+
// return pane.type === 'leafPane' ? (
|
|
36
|
+
// <LeafPaneView />
|
|
37
|
+
// ) : (
|
|
38
|
+
// <SplitPaneView />
|
|
39
|
+
// );
|
|
40
|
+
|
|
41
|
+
// This should go in LeafPaneView
|
|
42
|
+
return (
|
|
43
|
+
<>
|
|
44
|
+
<TabList
|
|
45
|
+
activeFileId={pane.activeFileId}
|
|
46
|
+
tabList={pane.tabList}
|
|
47
|
+
/>
|
|
48
|
+
{isClient && content && pane.activeFileId && (
|
|
49
|
+
<CodeEditor
|
|
50
|
+
customInteractRules={customInteractRules}
|
|
51
|
+
allowGlobals={allowGlobals}
|
|
52
|
+
/>
|
|
53
|
+
)}
|
|
54
|
+
{isClient &&
|
|
55
|
+
enableAIAssist &&
|
|
56
|
+
content &&
|
|
57
|
+
pane.activeFileId ? (
|
|
58
|
+
<AIAssistWidget
|
|
59
|
+
aiAssistEndpoint={aiAssistEndpoint}
|
|
60
|
+
aiAssistOptions={aiAssistOptions}
|
|
61
|
+
aiAssistTooltipText={aiAssistTooltipText}
|
|
62
|
+
aiAssistClickOverride={aiAssistClickOverride}
|
|
63
|
+
paneId={pane.id}
|
|
64
|
+
activeFileId={pane.activeFileId}
|
|
65
|
+
tabList={pane.tabList}
|
|
66
|
+
/>
|
|
67
|
+
) : null}
|
|
68
|
+
<RunCodeWidget />
|
|
69
|
+
</>
|
|
70
|
+
);
|
|
71
|
+
};
|
|
72
|
+
|
|
12
73
|
// The middle portion of the VZCode environment, containing:
|
|
13
74
|
// * The list of tabs at the top
|
|
14
75
|
// * The code editor itself
|
|
@@ -40,41 +101,34 @@ export const VZMiddle = ({
|
|
|
40
101
|
content,
|
|
41
102
|
localPresence,
|
|
42
103
|
docPresence,
|
|
43
|
-
|
|
104
|
+
pane,
|
|
105
|
+
activePane,
|
|
44
106
|
errorMessage,
|
|
45
107
|
} = useContext(VZCodeContext);
|
|
46
108
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
109
|
+
if (activePane.type !== 'leafPane') {
|
|
110
|
+
throw new Error('Expected leafPane');
|
|
111
|
+
}
|
|
112
|
+
// True if the editor panes should be shown.
|
|
113
|
+
const shouldShowEditorPanes: boolean =
|
|
114
|
+
activePane.activeFileId !== null;
|
|
53
115
|
|
|
54
|
-
return
|
|
116
|
+
return shouldShowEditorPanes ? (
|
|
55
117
|
<div
|
|
56
118
|
className="middle"
|
|
57
119
|
style={{ width: codeEditorWidth + 'px' }}
|
|
58
120
|
>
|
|
59
|
-
<
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
<AIAssistWidget
|
|
71
|
-
aiAssistEndpoint={aiAssistEndpoint}
|
|
72
|
-
aiAssistOptions={aiAssistOptions}
|
|
73
|
-
aiAssistTooltipText={aiAssistTooltipText}
|
|
74
|
-
aiAssistClickOverride={aiAssistClickOverride}
|
|
75
|
-
/>
|
|
76
|
-
) : null}
|
|
77
|
-
<RunCodeWidget />
|
|
121
|
+
<PaneView
|
|
122
|
+
pane={pane}
|
|
123
|
+
content={content}
|
|
124
|
+
customInteractRules={customInteractRules}
|
|
125
|
+
allowGlobals={allowGlobals}
|
|
126
|
+
enableAIAssist={enableAIAssist}
|
|
127
|
+
aiAssistEndpoint={aiAssistEndpoint}
|
|
128
|
+
aiAssistOptions={aiAssistOptions}
|
|
129
|
+
aiAssistTooltipText={aiAssistTooltipText}
|
|
130
|
+
aiAssistClickOverride={aiAssistClickOverride}
|
|
131
|
+
/>
|
|
78
132
|
<CodeErrorOverlay
|
|
79
133
|
errorMessage={errorMessage}
|
|
80
134
|
content={content}
|
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
useCallback,
|
|
7
7
|
useRef,
|
|
8
8
|
} from 'react';
|
|
9
|
-
|
|
10
9
|
import {
|
|
11
10
|
Side,
|
|
12
11
|
SplitPaneResizeContext,
|
|
@@ -44,9 +43,10 @@ export const VZResizer = ({
|
|
|
44
43
|
|
|
45
44
|
// If there is no active file, don't render the resizer
|
|
46
45
|
// for the right side.
|
|
47
|
-
const {
|
|
46
|
+
const { activePane } = useContext(VZCodeContext);
|
|
47
|
+
|
|
48
48
|
const shouldRenderResizer =
|
|
49
|
-
side === 'left' || activeFileId;
|
|
49
|
+
side === 'left' || activePane.activeFileId;
|
|
50
50
|
|
|
51
51
|
const previousClientX = useRef<number>(0);
|
|
52
52
|
|
|
@@ -1,44 +1,39 @@
|
|
|
1
1
|
import { useCallback, useContext } from 'react';
|
|
2
2
|
import { Item } from './Item';
|
|
3
3
|
import { FileId, PresenceIndicator } from '../../types';
|
|
4
|
-
import {
|
|
5
|
-
FileSVG,
|
|
6
|
-
JavaScriptSVG,
|
|
7
|
-
TypeScriptSVG,
|
|
8
|
-
ReactSVG,
|
|
9
|
-
SvelteSVG,
|
|
10
|
-
JsonSVG,
|
|
11
|
-
MarkdownSVG,
|
|
12
|
-
HtmlSVG,
|
|
13
|
-
CssSVG,
|
|
14
|
-
} from '../Icons';
|
|
15
4
|
import { VZCodeContext } from '../VZCodeContext';
|
|
5
|
+
import { FileTypeIcon } from './FileTypeIcon';
|
|
6
|
+
import { assignUserColor } from '../presenceColor';
|
|
16
7
|
|
|
17
|
-
|
|
18
|
-
|
|
8
|
+
const PresenceIndicators = ({
|
|
9
|
+
presence,
|
|
10
|
+
}: {
|
|
11
|
+
presence: PresenceIndicator[];
|
|
12
|
+
}) => {
|
|
13
|
+
return (
|
|
14
|
+
<div className="presence-indicators">
|
|
15
|
+
{presence.map((indicator, index) => {
|
|
16
|
+
// Get the raw RGB values from assignUserColor
|
|
17
|
+
const color = assignUserColor(indicator.username);
|
|
18
|
+
|
|
19
|
+
// Format it as `rgb()` directly in the component
|
|
20
|
+
const formattedColor = `rgb(${color})`;
|
|
19
21
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
return <CssSVG />;
|
|
36
|
-
case 'svelte':
|
|
37
|
-
return <SvelteSVG />;
|
|
38
|
-
default:
|
|
39
|
-
return <FileSVG />;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
22
|
+
//console.log(`Username: ${indicator.username}, Assigned Color: ${formattedColor}`);
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<div
|
|
26
|
+
key={index}
|
|
27
|
+
className="presence-indicator"
|
|
28
|
+
style={{ backgroundColor: formattedColor }}
|
|
29
|
+
>
|
|
30
|
+
{indicator.username[0]}
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
})}
|
|
34
|
+
</div>
|
|
35
|
+
);
|
|
36
|
+
};
|
|
42
37
|
|
|
43
38
|
export const FileListing = ({
|
|
44
39
|
name,
|
|
@@ -87,26 +82,9 @@ export const FileListing = ({
|
|
|
87
82
|
handleRenameClick={handleRenameClick}
|
|
88
83
|
isActive={isActive}
|
|
89
84
|
>
|
|
90
|
-
<
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
<div className="presence-indicators">
|
|
94
|
-
{presence.map((indicator, index) => (
|
|
95
|
-
<div
|
|
96
|
-
key={index}
|
|
97
|
-
className="presence-indicator"
|
|
98
|
-
>
|
|
99
|
-
{indicator.username[0]}{' '}
|
|
100
|
-
{/* Display the first letter of the username */}
|
|
101
|
-
</div>
|
|
102
|
-
))}
|
|
103
|
-
</div>
|
|
104
|
-
)}
|
|
105
|
-
<i className="file-icon">
|
|
106
|
-
{getExtensionIcon(name)}
|
|
107
|
-
</i>
|
|
108
|
-
{name}
|
|
109
|
-
</div>
|
|
85
|
+
<PresenceIndicators presence={presence} />
|
|
86
|
+
<FileTypeIcon name={name} />
|
|
87
|
+
{name}
|
|
110
88
|
</Item>
|
|
111
89
|
);
|
|
112
90
|
};
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
import {
|
|
3
|
+
FileSVG,
|
|
4
|
+
JavaScriptSVG,
|
|
5
|
+
TypeScriptSVG,
|
|
6
|
+
ReactSVG,
|
|
7
|
+
SvelteSVG,
|
|
8
|
+
JsonSVG,
|
|
9
|
+
MarkdownSVG,
|
|
10
|
+
HtmlSVG,
|
|
11
|
+
CssSVG,
|
|
12
|
+
} from '../Icons';
|
|
13
|
+
|
|
14
|
+
export function getExtensionIcon(fileName: string) {
|
|
15
|
+
const extension = fileName.split('.');
|
|
16
|
+
|
|
17
|
+
switch (extension[extension.length - 1]) {
|
|
18
|
+
case 'jsx':
|
|
19
|
+
case 'tsx':
|
|
20
|
+
return <ReactSVG />;
|
|
21
|
+
case 'js':
|
|
22
|
+
return <JavaScriptSVG />;
|
|
23
|
+
case 'ts':
|
|
24
|
+
return <TypeScriptSVG />;
|
|
25
|
+
case 'json':
|
|
26
|
+
return <JsonSVG />;
|
|
27
|
+
case 'md':
|
|
28
|
+
return <MarkdownSVG />;
|
|
29
|
+
case 'html':
|
|
30
|
+
return <HtmlSVG />;
|
|
31
|
+
case 'css':
|
|
32
|
+
return <CssSVG />;
|
|
33
|
+
case 'svelte':
|
|
34
|
+
return <SvelteSVG />;
|
|
35
|
+
default:
|
|
36
|
+
return <FileSVG />;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Various neat icons based on the file extension
|
|
41
|
+
export const FileTypeIcon = ({
|
|
42
|
+
name,
|
|
43
|
+
}: {
|
|
44
|
+
name: string;
|
|
45
|
+
}) => (
|
|
46
|
+
<i className="file-icon">
|
|
47
|
+
{useMemo(() => getExtensionIcon(name), [name])}
|
|
48
|
+
</i>
|
|
49
|
+
);
|
|
@@ -5,16 +5,14 @@ import {
|
|
|
5
5
|
useEffect,
|
|
6
6
|
useContext,
|
|
7
7
|
} from 'react';
|
|
8
|
-
import {
|
|
8
|
+
import { ItemId } from '../../types';
|
|
9
|
+
import { EditSVG, TrashSVG } from '../Icons';
|
|
9
10
|
import { Tooltip, OverlayTrigger } from '../bootstrap';
|
|
11
|
+
import { VZCodeContext } from '../VZCodeContext';
|
|
12
|
+
import { FileTypeIcon } from './FileTypeIcon';
|
|
10
13
|
|
|
11
14
|
// TODO consider moving this up to a higher level of the component tree
|
|
12
15
|
import { DeleteConfirmationModal } from './DeleteConfirmationModal';
|
|
13
|
-
import { VZCodeContext } from '../VZCodeContext';
|
|
14
|
-
import { ItemId } from '../../types';
|
|
15
|
-
import { getExtensionIcon } from './FileListing';
|
|
16
|
-
import { SplitEditorSVG } from '../Icons/SplitEditorSVG';
|
|
17
|
-
import { SplitPaneResizeProvider } from '../SplitPaneResizeContext';
|
|
18
16
|
|
|
19
17
|
const enableRenameDirectory = true;
|
|
20
18
|
|
|
@@ -169,9 +167,7 @@ export const Item = ({
|
|
|
169
167
|
<div className="name">
|
|
170
168
|
{isRenaming ? (
|
|
171
169
|
<>
|
|
172
|
-
<
|
|
173
|
-
{getExtensionIcon(renameValue)}
|
|
174
|
-
</i>
|
|
170
|
+
<FileTypeIcon name={renameValue} />
|
|
175
171
|
<input
|
|
176
172
|
className="rename-input"
|
|
177
173
|
ref={renameInputRef}
|