vzcode 1.10.0 → 1.12.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/README.md +1 -1
- package/dist/assets/{index-DXNuoOqQ.js → index-4cYZN5Uf.js} +57 -57
- package/dist/assets/{index--bvX81xc.js → index-CvSVuMne.js} +57 -57
- package/dist/assets/worker-CJWrLBN2.js +286 -0
- package/dist/index.html +1 -1
- package/package.json +13 -12
- package/src/client/AIAssist/AIAssistCodeMirrorKeyMap.ts +5 -2
- package/src/client/AIAssist/startAIAssist.ts +1 -1
- package/src/client/CodeEditor/getOrCreateEditor.ts +4 -0
- package/src/client/CodeEditor/index.tsx +2 -0
- package/src/client/CodeEditor/json1PresenceDisplay.ts +128 -90
- package/src/client/TabList/Tab.tsx +1 -2
- package/src/client/TabList/index.tsx +1 -1
- package/src/client/VZCodeContext.tsx +17 -14
- package/src/client/VZKeyboardShortcutsDoc.tsx +2 -1
- package/src/client/VZSidebar/Search.tsx +7 -2
- package/src/client/VZSidebar/index.tsx +87 -24
- package/src/client/tabsSearchParameters.ts +1 -2
- package/src/client/useActions.ts +10 -1
- package/src/client/useKeyboardShortcuts.ts +31 -1
- package/src/client/useURLSync.ts +1 -2
- package/src/client/vzReducer/closeTabReducer.test.ts +49 -33
- package/src/client/vzReducer/closeTabsReducer.ts +51 -19
- package/src/client/vzReducer/createInitialState.ts +8 -3
- package/src/client/vzReducer/findPane.ts +19 -0
- package/src/client/vzReducer/index.ts +17 -25
- package/src/client/vzReducer/openTabReducer.test.ts +38 -21
- package/src/client/vzReducer/openTabReducer.ts +26 -10
- package/src/client/vzReducer/searchReducer.ts +21 -1
- package/src/client/vzReducer/setActiveFileIdReducer.ts +23 -4
- package/src/client/vzReducer/setActiveFileLeftRightReducer.ts +37 -8
- package/src/client/vzReducer/updatePane.ts +44 -0
- package/src/server/index.js +1 -0
- package/src/types.ts +69 -70
- package/dist/assets/worker-Cs0ZU3m1.js +0 -291
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
FileId,
|
|
3
|
+
Pane,
|
|
4
|
+
PaneId,
|
|
3
5
|
SearchFileVisibility,
|
|
4
6
|
SearchResults,
|
|
5
7
|
ShareDBDoc,
|
|
@@ -24,18 +26,18 @@ import {
|
|
|
24
26
|
setSearchReducer,
|
|
25
27
|
setSearchResultsReducer,
|
|
26
28
|
setSearchFileVisibilityReducer,
|
|
29
|
+
toggleSearchFocusedReducer,
|
|
27
30
|
} from './searchReducer';
|
|
28
31
|
import { toggleAutoFollowReducer } from './toggleAutoFollowReducer';
|
|
29
32
|
export { createInitialState } from './createInitialState';
|
|
30
33
|
|
|
31
34
|
// The shape of the state managed by the reducer.
|
|
32
35
|
export type VZState = {
|
|
33
|
-
// The
|
|
34
|
-
|
|
36
|
+
// The state of the split pane (tree data structure).
|
|
37
|
+
pane: Pane;
|
|
35
38
|
|
|
36
|
-
// The
|
|
37
|
-
|
|
38
|
-
activeFileId: FileId | null;
|
|
39
|
+
// The id of the currently active pane.
|
|
40
|
+
activePaneId: PaneId;
|
|
39
41
|
|
|
40
42
|
// The theme that is currently active.
|
|
41
43
|
theme: ThemeLabel;
|
|
@@ -86,7 +88,11 @@ export type VZAction =
|
|
|
86
88
|
|
|
87
89
|
// `close_tabs`
|
|
88
90
|
// * Closes a set of tabs.
|
|
89
|
-
| {
|
|
91
|
+
| {
|
|
92
|
+
type: 'close_tabs';
|
|
93
|
+
fileIdsToClose: Array<FileId>;
|
|
94
|
+
// The pane id to close tabs from.
|
|
95
|
+
}
|
|
90
96
|
|
|
91
97
|
// `set_theme`
|
|
92
98
|
// * Sets the theme.
|
|
@@ -121,6 +127,10 @@ export type VZAction =
|
|
|
121
127
|
visibility: SearchFileVisibility;
|
|
122
128
|
}
|
|
123
129
|
|
|
130
|
+
// `toggle_search_focused`
|
|
131
|
+
// * Toggles focused variable to trigger search input focus
|
|
132
|
+
| { type: 'toggle_search_focused' }
|
|
133
|
+
|
|
124
134
|
// `editor_no_longer_wants_focus`
|
|
125
135
|
// * Sets `editorWantsFocus` to `false`.
|
|
126
136
|
| { type: 'editor_no_longer_wants_focus' }
|
|
@@ -133,25 +143,6 @@ export type VZAction =
|
|
|
133
143
|
// * Toggles the auto-follow feature.
|
|
134
144
|
| { type: 'toggle_auto_follow' };
|
|
135
145
|
|
|
136
|
-
// Representation of an open tab.
|
|
137
|
-
export type TabState = {
|
|
138
|
-
// `fileId`
|
|
139
|
-
// The ID of the file that the tab represents.
|
|
140
|
-
fileId: FileId;
|
|
141
|
-
|
|
142
|
-
// `isTransient`
|
|
143
|
-
// Represents whether the tab is temporary or persistent.
|
|
144
|
-
// * `true` if the tab is temporary, meaning its text
|
|
145
|
-
// appears as italic, and it will be automatically
|
|
146
|
-
// closed when the user switches to another file.
|
|
147
|
-
// If `true` and the tab is opened, the editor will not focus.
|
|
148
|
-
// * `false` or `undefined` if the tab is persistent, meaning its text
|
|
149
|
-
// appears as normal, and it will not be automatically
|
|
150
|
-
// closed when the user switches to another file.
|
|
151
|
-
// If `false` and the tab is opened, the editor will focus.
|
|
152
|
-
isTransient?: boolean;
|
|
153
|
-
};
|
|
154
|
-
|
|
155
146
|
const reducers = [
|
|
156
147
|
setActiveFileIdReducer,
|
|
157
148
|
setActiveFileLeftReducer,
|
|
@@ -162,6 +153,7 @@ const reducers = [
|
|
|
162
153
|
setSearchReducer,
|
|
163
154
|
setSearchResultsReducer,
|
|
164
155
|
setSearchFileVisibilityReducer,
|
|
156
|
+
toggleSearchFocusedReducer,
|
|
165
157
|
setIsSearchOpenReducer,
|
|
166
158
|
setIsSettingsOpenReducer,
|
|
167
159
|
setIsDocOpenReducer,
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { describe, expect, it } from 'vitest';
|
|
1
|
+
import { assert, describe, expect, it } from 'vitest';
|
|
2
2
|
import { openTabReducer } from './openTabReducer';
|
|
3
3
|
import { VZAction, VZState, createInitialState } from '.';
|
|
4
4
|
import { defaultTheme } from '../themes';
|
|
@@ -16,16 +16,22 @@ describe('openTabReducer', () => {
|
|
|
16
16
|
};
|
|
17
17
|
const newState = openTabReducer(initialState, action);
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
expect(newState.tabList
|
|
21
|
-
expect(newState.tabList[0].
|
|
22
|
-
expect(newState.
|
|
19
|
+
assert(newState.pane.type === 'leafPane');
|
|
20
|
+
expect(newState.pane.tabList.length).toBe(1);
|
|
21
|
+
expect(newState.pane.tabList[0].fileId).toBe('file1');
|
|
22
|
+
expect(newState.pane.tabList[0].isTransient).toBe(
|
|
23
|
+
false,
|
|
24
|
+
);
|
|
25
|
+
expect(newState.pane.activeFileId).toBe('file1');
|
|
23
26
|
});
|
|
24
27
|
|
|
25
28
|
it('Replaces a transient tab', () => {
|
|
26
29
|
const stateWithTransientTab = {
|
|
27
30
|
...initialState,
|
|
28
|
-
|
|
31
|
+
pane: {
|
|
32
|
+
...initialState.pane,
|
|
33
|
+
tabList: [{ fileId: 'file2', isTransient: true }],
|
|
34
|
+
},
|
|
29
35
|
};
|
|
30
36
|
const action: VZAction = {
|
|
31
37
|
type: 'open_tab',
|
|
@@ -37,16 +43,20 @@ describe('openTabReducer', () => {
|
|
|
37
43
|
action,
|
|
38
44
|
);
|
|
39
45
|
|
|
40
|
-
|
|
41
|
-
expect(newState.tabList
|
|
42
|
-
expect(newState.tabList[0].
|
|
43
|
-
expect(newState.
|
|
46
|
+
assert(newState.pane.type === 'leafPane');
|
|
47
|
+
expect(newState.pane.tabList.length).toBe(1);
|
|
48
|
+
expect(newState.pane.tabList[0].fileId).toBe('file1');
|
|
49
|
+
expect(newState.pane.tabList[0].isTransient).toBe(true);
|
|
50
|
+
expect(newState.pane.activeFileId).toBe('file1');
|
|
44
51
|
});
|
|
45
52
|
|
|
46
53
|
it('Does not modify a non-transient tab', () => {
|
|
47
54
|
const stateWithNonTransientTab = {
|
|
48
55
|
...initialState,
|
|
49
|
-
|
|
56
|
+
pane: {
|
|
57
|
+
...initialState.pane,
|
|
58
|
+
tabList: [{ fileId: 'file1', isTransient: false }],
|
|
59
|
+
},
|
|
50
60
|
};
|
|
51
61
|
const action: VZAction = {
|
|
52
62
|
type: 'open_tab',
|
|
@@ -58,19 +68,25 @@ describe('openTabReducer', () => {
|
|
|
58
68
|
action,
|
|
59
69
|
);
|
|
60
70
|
|
|
61
|
-
|
|
62
|
-
expect(newState.tabList
|
|
63
|
-
expect(newState.tabList[0].
|
|
64
|
-
expect(newState.
|
|
71
|
+
assert(newState.pane.type === 'leafPane');
|
|
72
|
+
expect(newState.pane.tabList.length).toBe(1);
|
|
73
|
+
expect(newState.pane.tabList[0].fileId).toBe('file1');
|
|
74
|
+
expect(newState.pane.tabList[0].isTransient).toBe(
|
|
75
|
+
false,
|
|
76
|
+
); // should remain non-transient
|
|
77
|
+
expect(newState.pane.activeFileId).toBe('file1');
|
|
65
78
|
});
|
|
66
79
|
|
|
67
80
|
it('Activates an already open tab', () => {
|
|
68
81
|
const stateWithMultipleTabs = {
|
|
69
82
|
...initialState,
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
83
|
+
pane: {
|
|
84
|
+
...initialState.pane,
|
|
85
|
+
tabList: [
|
|
86
|
+
{ fileId: 'file1', isTransient: false },
|
|
87
|
+
{ fileId: 'file2', isTransient: false },
|
|
88
|
+
],
|
|
89
|
+
},
|
|
74
90
|
};
|
|
75
91
|
const action: VZAction = {
|
|
76
92
|
type: 'open_tab',
|
|
@@ -82,8 +98,9 @@ describe('openTabReducer', () => {
|
|
|
82
98
|
action,
|
|
83
99
|
);
|
|
84
100
|
|
|
85
|
-
|
|
86
|
-
expect(newState.
|
|
101
|
+
assert(newState.pane.type === 'leafPane');
|
|
102
|
+
expect(newState.pane.tabList.length).toBe(2);
|
|
103
|
+
expect(newState.pane.activeFileId).toBe('file1');
|
|
87
104
|
});
|
|
88
105
|
|
|
89
106
|
it('Sets editorWantsFocus to true for non-transient tabs', () => {
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { VZAction, VZState } from '.';
|
|
2
|
+
import { Pane, TabState } from '../../types';
|
|
3
|
+
import { findPane } from './findPane';
|
|
4
|
+
import { updatePane } from './updatePane';
|
|
2
5
|
|
|
3
6
|
export const openTabReducer = (
|
|
4
7
|
state: VZState,
|
|
@@ -6,17 +9,26 @@ export const openTabReducer = (
|
|
|
6
9
|
): VZState => {
|
|
7
10
|
if (action.type !== 'open_tab') return state;
|
|
8
11
|
|
|
12
|
+
const { pane, activePaneId } = state;
|
|
13
|
+
const activePane: Pane = findPane(pane, activePaneId);
|
|
14
|
+
|
|
15
|
+
if (activePane.type !== 'leafPane') {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'closeTabsReducer: activePane is not a leafPane',
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
|
|
9
21
|
// Check if the tab is already open and if it's transient.
|
|
10
|
-
const existingTabIndex =
|
|
22
|
+
const existingTabIndex = activePane.tabList.findIndex(
|
|
11
23
|
(tab) => tab.fileId === action.fileId,
|
|
12
24
|
);
|
|
13
25
|
const tabExists = existingTabIndex !== -1;
|
|
14
26
|
const existingTabIsTransient =
|
|
15
27
|
tabExists &&
|
|
16
|
-
|
|
28
|
+
activePane.tabList[existingTabIndex].isTransient;
|
|
17
29
|
|
|
18
30
|
// Find if there's any other transient tab.
|
|
19
|
-
const transientTabIndex =
|
|
31
|
+
const transientTabIndex = activePane.tabList.findIndex(
|
|
20
32
|
(tab) =>
|
|
21
33
|
tab.isTransient && tab.fileId !== action.fileId,
|
|
22
34
|
);
|
|
@@ -31,25 +43,29 @@ export const openTabReducer = (
|
|
|
31
43
|
|
|
32
44
|
if (tabExists) {
|
|
33
45
|
if (existingTabIsTransient) {
|
|
34
|
-
newTabList =
|
|
46
|
+
newTabList = activePane.tabList.map((tabState) =>
|
|
35
47
|
tabState.fileId === action.fileId
|
|
36
48
|
? newTabState
|
|
37
49
|
: tabState,
|
|
38
50
|
);
|
|
39
51
|
} else {
|
|
40
|
-
newTabList = [...
|
|
52
|
+
newTabList = [...activePane.tabList];
|
|
41
53
|
}
|
|
42
54
|
} else if (transientTabIndex !== -1) {
|
|
43
|
-
newTabList = [...
|
|
55
|
+
newTabList = [...activePane.tabList];
|
|
44
56
|
newTabList[transientTabIndex] = newTabState;
|
|
45
57
|
} else {
|
|
46
|
-
newTabList = [...
|
|
58
|
+
newTabList = [...activePane.tabList, newTabState];
|
|
47
59
|
}
|
|
48
60
|
|
|
49
61
|
return {
|
|
50
62
|
...state,
|
|
51
|
-
|
|
52
|
-
|
|
63
|
+
pane: updatePane({
|
|
64
|
+
pane,
|
|
65
|
+
activePaneId,
|
|
66
|
+
newTabList,
|
|
67
|
+
newActiveFileId: action.fileId,
|
|
68
|
+
}),
|
|
53
69
|
|
|
54
70
|
// If the tab is persistent, the editor should focus on the next render.
|
|
55
71
|
editorWantsFocus: !action.isTransient,
|
|
@@ -74,7 +74,11 @@ export const setSearchReducer = (
|
|
|
74
74
|
action.type === 'set_search'
|
|
75
75
|
? {
|
|
76
76
|
...state,
|
|
77
|
-
search: {
|
|
77
|
+
search: {
|
|
78
|
+
pattern: action.value,
|
|
79
|
+
results: {},
|
|
80
|
+
focused: true,
|
|
81
|
+
},
|
|
78
82
|
}
|
|
79
83
|
: state;
|
|
80
84
|
|
|
@@ -91,6 +95,7 @@ export const setSearchResultsReducer = (
|
|
|
91
95
|
action.files,
|
|
92
96
|
state.search.pattern,
|
|
93
97
|
),
|
|
98
|
+
focused: state.search.focused,
|
|
94
99
|
},
|
|
95
100
|
}
|
|
96
101
|
: state;
|
|
@@ -109,6 +114,21 @@ export const setSearchFileVisibilityReducer = (
|
|
|
109
114
|
action.id,
|
|
110
115
|
action.visibility,
|
|
111
116
|
),
|
|
117
|
+
focused: state.search.focused,
|
|
118
|
+
},
|
|
119
|
+
}
|
|
120
|
+
: state;
|
|
121
|
+
|
|
122
|
+
export const toggleSearchFocusedReducer = (
|
|
123
|
+
state: VZState,
|
|
124
|
+
action: VZAction,
|
|
125
|
+
): VZState =>
|
|
126
|
+
action.type === 'toggle_search_focused'
|
|
127
|
+
? {
|
|
128
|
+
...state,
|
|
129
|
+
search: {
|
|
130
|
+
...state.search,
|
|
131
|
+
focused: !state.search.focused,
|
|
112
132
|
},
|
|
113
133
|
}
|
|
114
134
|
: state;
|
|
@@ -1,9 +1,28 @@
|
|
|
1
1
|
import { VZAction, VZState } from '.';
|
|
2
|
+
import { Pane } from '../../types';
|
|
3
|
+
import { findPane } from './findPane';
|
|
4
|
+
import { updatePane } from './updatePane';
|
|
2
5
|
|
|
3
6
|
export const setActiveFileIdReducer = (
|
|
4
7
|
state: VZState,
|
|
5
8
|
action: VZAction,
|
|
6
|
-
): VZState =>
|
|
7
|
-
action.type
|
|
8
|
-
|
|
9
|
-
|
|
9
|
+
): VZState => {
|
|
10
|
+
if (action.type !== 'set_active_file_id') return state;
|
|
11
|
+
|
|
12
|
+
const { pane, activePaneId } = state;
|
|
13
|
+
const activePane: Pane = findPane(pane, activePaneId);
|
|
14
|
+
|
|
15
|
+
if (activePane.type !== 'leafPane') {
|
|
16
|
+
throw new Error(
|
|
17
|
+
'closeTabsReducer: activePane is not a leafPane',
|
|
18
|
+
);
|
|
19
|
+
}
|
|
20
|
+
return {
|
|
21
|
+
...state,
|
|
22
|
+
pane: updatePane({
|
|
23
|
+
pane,
|
|
24
|
+
activePaneId,
|
|
25
|
+
newActiveFileId: action.activeFileId,
|
|
26
|
+
}),
|
|
27
|
+
};
|
|
28
|
+
};
|
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
import { VZAction, VZState } from '.';
|
|
2
|
+
import { Pane } from '../../types';
|
|
3
|
+
import { findPane } from './findPane';
|
|
4
|
+
import { updatePane } from './updatePane';
|
|
2
5
|
|
|
3
6
|
export const setActiveFileLeftReducer = (
|
|
4
7
|
state: VZState,
|
|
@@ -8,18 +11,31 @@ export const setActiveFileLeftReducer = (
|
|
|
8
11
|
return state;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
const { pane, activePaneId } = state;
|
|
15
|
+
const activePane: Pane = findPane(pane, activePaneId);
|
|
16
|
+
|
|
17
|
+
if (activePane.type !== 'leafPane') {
|
|
18
|
+
throw new Error(
|
|
19
|
+
'closeTabsReducer: activePane is not a leafPane',
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
let index = activePane.tabList.findIndex(
|
|
24
|
+
(tab) => tab.fileId === activePane.activeFileId,
|
|
13
25
|
);
|
|
14
26
|
|
|
15
27
|
index -= 1;
|
|
16
28
|
if (index < 0) {
|
|
17
|
-
index =
|
|
29
|
+
index = activePane.tabList.length - 1;
|
|
18
30
|
}
|
|
19
31
|
|
|
20
32
|
return {
|
|
21
33
|
...state,
|
|
22
|
-
|
|
34
|
+
pane: updatePane({
|
|
35
|
+
pane,
|
|
36
|
+
activePaneId,
|
|
37
|
+
newActiveFileId: activePane.tabList[index].fileId,
|
|
38
|
+
}),
|
|
23
39
|
};
|
|
24
40
|
};
|
|
25
41
|
|
|
@@ -31,17 +47,30 @@ export const setActiveFileRightReducer = (
|
|
|
31
47
|
return state;
|
|
32
48
|
}
|
|
33
49
|
|
|
34
|
-
|
|
35
|
-
|
|
50
|
+
const { pane, activePaneId } = state;
|
|
51
|
+
const activePane: Pane = findPane(pane, activePaneId);
|
|
52
|
+
|
|
53
|
+
if (activePane.type !== 'leafPane') {
|
|
54
|
+
throw new Error(
|
|
55
|
+
'closeTabsReducer: activePane is not a leafPane',
|
|
56
|
+
);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
let index = activePane.tabList.findIndex(
|
|
60
|
+
(tab) => tab.fileId === activePane.activeFileId,
|
|
36
61
|
);
|
|
37
62
|
|
|
38
63
|
index += 1;
|
|
39
|
-
if (index >
|
|
64
|
+
if (index > activePane.tabList.length - 1) {
|
|
40
65
|
index = 0;
|
|
41
66
|
}
|
|
42
67
|
|
|
43
68
|
return {
|
|
44
69
|
...state,
|
|
45
|
-
|
|
70
|
+
pane: updatePane({
|
|
71
|
+
pane,
|
|
72
|
+
activePaneId,
|
|
73
|
+
newActiveFileId: activePane.tabList[index].fileId,
|
|
74
|
+
}),
|
|
46
75
|
};
|
|
47
76
|
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import {
|
|
2
|
+
FileId,
|
|
3
|
+
Pane,
|
|
4
|
+
PaneId,
|
|
5
|
+
TabState,
|
|
6
|
+
} from '../../types';
|
|
7
|
+
|
|
8
|
+
// Immutable update pattern for updating a pane's tab list.
|
|
9
|
+
export const updatePane = ({
|
|
10
|
+
pane,
|
|
11
|
+
activePaneId,
|
|
12
|
+
newTabList,
|
|
13
|
+
newActiveFileId,
|
|
14
|
+
}: {
|
|
15
|
+
pane: Pane;
|
|
16
|
+
activePaneId: PaneId;
|
|
17
|
+
newTabList?: Array<TabState>;
|
|
18
|
+
newActiveFileId?: FileId | null;
|
|
19
|
+
}): Pane =>
|
|
20
|
+
pane.type === 'splitPane'
|
|
21
|
+
? {
|
|
22
|
+
...pane,
|
|
23
|
+
children: pane.children.map((child) =>
|
|
24
|
+
updatePane({
|
|
25
|
+
pane: child,
|
|
26
|
+
activePaneId,
|
|
27
|
+
newTabList,
|
|
28
|
+
newActiveFileId,
|
|
29
|
+
}),
|
|
30
|
+
),
|
|
31
|
+
}
|
|
32
|
+
: pane.id === activePaneId
|
|
33
|
+
? {
|
|
34
|
+
...pane,
|
|
35
|
+
tabList:
|
|
36
|
+
newTabList !== undefined
|
|
37
|
+
? newTabList
|
|
38
|
+
: pane.tabList,
|
|
39
|
+
activeFileId:
|
|
40
|
+
newActiveFileId !== undefined
|
|
41
|
+
? newActiveFileId
|
|
42
|
+
: pane.activeFileId,
|
|
43
|
+
}
|
|
44
|
+
: pane;
|
package/src/server/index.js
CHANGED
|
@@ -313,6 +313,7 @@ server.listen(port, async () => {
|
|
|
313
313
|
// Sets the port to the one specified in the environment
|
|
314
314
|
// variable (for development) or the default port.
|
|
315
315
|
let livePort = process.env.EDITOR_PORT || port;
|
|
316
|
+
console.log(`EDITOR_PORT: ${process.env.EDITOR_PORT}`);
|
|
316
317
|
console.log(
|
|
317
318
|
`Editor is live at http://localhost:${livePort}`,
|
|
318
319
|
);
|
package/src/types.ts
CHANGED
|
@@ -80,8 +80,70 @@ export interface SearchFile {
|
|
|
80
80
|
export interface SearchResults {
|
|
81
81
|
pattern: string;
|
|
82
82
|
results: SearchResult;
|
|
83
|
+
focused: boolean;
|
|
83
84
|
}
|
|
84
85
|
|
|
86
|
+
// Representation of an open tab.
|
|
87
|
+
export type TabState = {
|
|
88
|
+
// `fileId`
|
|
89
|
+
// The ID of the file that the tab represents.
|
|
90
|
+
fileId: FileId;
|
|
91
|
+
|
|
92
|
+
// `isTransient`
|
|
93
|
+
// Represents whether the tab is temporary or persistent.
|
|
94
|
+
// * `true` if the tab is temporary, meaning its text
|
|
95
|
+
// appears as italic, and it will be automatically
|
|
96
|
+
// closed when the user switches to another file.
|
|
97
|
+
// If `true` and the tab is opened, the editor will not focus.
|
|
98
|
+
// * `false` or `undefined` if the tab is persistent, meaning its text
|
|
99
|
+
// appears as normal, and it will not be automatically
|
|
100
|
+
// closed when the user switches to another file.
|
|
101
|
+
// If `false` and the tab is opened, the editor will focus.
|
|
102
|
+
isTransient?: boolean;
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
// PaneId
|
|
106
|
+
// * A unique ID for a pane.
|
|
107
|
+
// * This is a random string.
|
|
108
|
+
export type PaneId = string;
|
|
109
|
+
|
|
110
|
+
// The leaf node of the tree data structure
|
|
111
|
+
export type LeafPane = {
|
|
112
|
+
type: 'leafPane';
|
|
113
|
+
// The list of tabs
|
|
114
|
+
// Mutually exclusive with `children`.
|
|
115
|
+
tabList: Array<TabState>;
|
|
116
|
+
|
|
117
|
+
// The ID of the file that is currently active
|
|
118
|
+
// within this leaf pane.
|
|
119
|
+
// Invariant: `activeFileId` is always in `tabList`.
|
|
120
|
+
activeFileId: FileId | null;
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
// Internal node of the tree data structure
|
|
124
|
+
export type SplitPane = {
|
|
125
|
+
type: 'splitPane';
|
|
126
|
+
|
|
127
|
+
// Which orientation is it? Vertical split or horizontal split?
|
|
128
|
+
// Applies only to `children`
|
|
129
|
+
orientation: 'vertical' | 'horizontal';
|
|
130
|
+
|
|
131
|
+
// The children panels
|
|
132
|
+
// Mutually exclusive with `tabList`.
|
|
133
|
+
children: Array<Pane>;
|
|
134
|
+
};
|
|
135
|
+
|
|
136
|
+
// The node data structure of the split pane tree
|
|
137
|
+
export type Pane = {
|
|
138
|
+
// Every pane gets a unique ID,
|
|
139
|
+
// so we can refer to it in actions.
|
|
140
|
+
id: PaneId;
|
|
141
|
+
|
|
142
|
+
// The type of the pane
|
|
143
|
+
// Either a leaf pane or a split pane.
|
|
144
|
+
type: 'leafPane' | 'splitPane';
|
|
145
|
+
} & (LeafPane | SplitPane);
|
|
146
|
+
|
|
85
147
|
export type JSONOp = any;
|
|
86
148
|
|
|
87
149
|
// `ShareDBDoc`
|
|
@@ -115,57 +177,6 @@ export type ShareDBDoc<T> = {
|
|
|
115
177
|
// Generated by the client.
|
|
116
178
|
export type AIStreamId = string;
|
|
117
179
|
|
|
118
|
-
// // TODO define this interface.
|
|
119
|
-
// export type AIStreamStatus = {
|
|
120
|
-
// // This field is managed by the client.
|
|
121
|
-
// // * `true` if the client wants the server to start the generation.
|
|
122
|
-
// // * `false` if the client does not want the server to start the generation.
|
|
123
|
-
// clientWantsToStart: boolean;
|
|
124
|
-
|
|
125
|
-
// // This field is managed by the server.
|
|
126
|
-
// // * `true` if the server is running the generation.
|
|
127
|
-
// // * `false` if the server is not running the generation.
|
|
128
|
-
// serverIsRunning: boolean;
|
|
129
|
-
|
|
130
|
-
// text: string;
|
|
131
|
-
|
|
132
|
-
// startingInsertionCursor: number;
|
|
133
|
-
// fileId: FileId;
|
|
134
|
-
// };
|
|
135
|
-
|
|
136
|
-
/// Alternative universe
|
|
137
|
-
|
|
138
|
-
// // // If the generation started yet or not
|
|
139
|
-
// // // * If not, the server will start it.
|
|
140
|
-
// // started: boolean;
|
|
141
|
-
|
|
142
|
-
// // Required?
|
|
143
|
-
// // aiStreamId: AIStreamId
|
|
144
|
-
|
|
145
|
-
// // The generation status
|
|
146
|
-
// // * "running" if the generation is running
|
|
147
|
-
// // * "finished" if the generation is finished
|
|
148
|
-
// // * "error" if the generation errored
|
|
149
|
-
// // * "stopped" if the generation was stopped
|
|
150
|
-
// status:
|
|
151
|
-
// | 'unstarted'
|
|
152
|
-
// | 'running'
|
|
153
|
-
// | 'finished'
|
|
154
|
-
// | 'error'
|
|
155
|
-
// | 'stopped';
|
|
156
|
-
|
|
157
|
-
// // Possible states:
|
|
158
|
-
// // * { started: 'unstarted' } - client added this,
|
|
159
|
-
// // It should trigger the server to start the generation.
|
|
160
|
-
// // * { status: 'running' } - server added this,
|
|
161
|
-
// // It indicates that the generation is running.
|
|
162
|
-
// // * { status: 'finished' } - server added this,
|
|
163
|
-
// // It indicates that the generation is finished.
|
|
164
|
-
// // * { status: 'stopped' } - server added this,
|
|
165
|
-
// // It indicates that the generation was stopped.
|
|
166
|
-
// //
|
|
167
|
-
// // After `status` transitions to `finished` or `stopped`,
|
|
168
|
-
|
|
169
180
|
// The ShareDB document type for VZCode.
|
|
170
181
|
export type VZCodeContent = {
|
|
171
182
|
// `files`
|
|
@@ -179,25 +190,13 @@ export type VZCodeContent = {
|
|
|
179
190
|
// * `false` or `undefined` when they are not (e.g. normal typing)
|
|
180
191
|
// * Hot reloading is debounced when this is `false`.
|
|
181
192
|
isInteracting?: boolean;
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
// client and server.
|
|
190
|
-
// * This can power the transition of the icon from
|
|
191
|
-
// lightning bolt to stop sign and back (when stream finishes)
|
|
192
|
-
// aiStreams?: {
|
|
193
|
-
// // These need to be removed at some point?
|
|
194
|
-
// [aiStreamId: AIStreamId]: {
|
|
195
|
-
// AIStreamStatus: AIStreamStatus;
|
|
196
|
-
// };
|
|
197
|
-
// };
|
|
198
|
-
|
|
199
|
-
// TODO consider is there a way to replace the HTTP request to
|
|
200
|
-
// the AIAssist endpoint with a manipulation of the ShareDB document?
|
|
193
|
+
};
|
|
194
|
+
// Example Presence object, from ShareDB:
|
|
195
|
+
// {"start":["files","69064344","text",183],"end":["files","69064344","text",183],"username":"Jim"}
|
|
196
|
+
export type Presence = {
|
|
197
|
+
start: Array<string | number>;
|
|
198
|
+
end: Array<string | number>;
|
|
199
|
+
username: Username;
|
|
201
200
|
};
|
|
202
201
|
|
|
203
202
|
// An id used for presence.
|