vzcode 1.12.0 → 1.14.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.
@@ -24,4 +24,5 @@ export const createInitialState = ({
24
24
  editorWantsFocus: false,
25
25
  username: initialUsername,
26
26
  enableAutoFollow: false,
27
+ sidebarPresenceIndicators: [],
27
28
  });
@@ -2,6 +2,7 @@ import {
2
2
  FileId,
3
3
  Pane,
4
4
  PaneId,
5
+ PresenceIndicator,
5
6
  SearchFileVisibility,
6
7
  SearchResults,
7
8
  ShareDBDoc,
@@ -29,6 +30,8 @@ import {
29
30
  toggleSearchFocusedReducer,
30
31
  } from './searchReducer';
31
32
  import { toggleAutoFollowReducer } from './toggleAutoFollowReducer';
33
+ import { updatePresenceIndicatorReducer } from './updatePresenceIndicatorReducer';
34
+ import { splitCurrentPaneReducer } from './splitCurrentPaneReducer';
32
35
  export { createInitialState } from './createInitialState';
33
36
 
34
37
  // The shape of the state managed by the reducer.
@@ -63,6 +66,10 @@ export type VZState = {
63
66
  // This is a feature that automatically scrolls the editor to the
64
67
  // currently active remote user's cursor position.
65
68
  enableAutoFollow: boolean;
69
+
70
+ // The list of remote users and which file they have open,
71
+ // for presence display in the sidebar.
72
+ sidebarPresenceIndicators: Array<PresenceIndicator>;
66
73
  };
67
74
 
68
75
  // The shape of the actions that can be dispatched to the reducer.
@@ -139,9 +146,19 @@ export type VZAction =
139
146
  // * Sets the username.
140
147
  | { type: 'set_username'; username: Username }
141
148
 
142
- // `toggle_auto_follow
149
+ // `toggle_auto_follow`
143
150
  // * Toggles the auto-follow feature.
144
- | { type: 'toggle_auto_follow' };
151
+ | { type: 'toggle_auto_follow' }
152
+
153
+ // `update_presence_indicator
154
+ // * Updates a single presence indicator
155
+ | {
156
+ type: 'update_presence_indicator';
157
+ presenceIndicator: PresenceIndicator;
158
+ }
159
+
160
+ // `split_current_pane`
161
+ | { type: 'split_current_pane' };
145
162
 
146
163
  const reducers = [
147
164
  setActiveFileIdReducer,
@@ -160,6 +177,8 @@ const reducers = [
160
177
  editorNoLongerWantsFocusReducer,
161
178
  setUsernameReducer,
162
179
  toggleAutoFollowReducer,
180
+ updatePresenceIndicatorReducer,
181
+ splitCurrentPaneReducer,
163
182
  ];
164
183
 
165
184
  export const vzReducer = (
@@ -0,0 +1,66 @@
1
+ import { PaneId, Pane } from '../../types';
2
+ import { VZAction, VZState } from '.';
3
+ import { updatePane } from './updatePane';
4
+
5
+ export const splitCurrentPaneReducer = (
6
+ state: VZState,
7
+ action: VZAction,
8
+ ): VZState => {
9
+ // console.log('splitCurrentPaneReducer');
10
+ if (action.type !== 'split_current_pane') {
11
+ return state;
12
+ }
13
+
14
+ const activePaneId = state.activePaneId;
15
+
16
+ const newLeafPane1: Pane = {
17
+ id: `${activePaneId}-1`, // Generate unique IDs for new panes
18
+ type: 'leafPane',
19
+ tabList: [],
20
+ activeFileId: null,
21
+ };
22
+
23
+ const newLeafPane2: Pane = {
24
+ id: `${activePaneId}-2`,
25
+ type: 'leafPane',
26
+ tabList: [],
27
+ activeFileId: null,
28
+ };
29
+
30
+ const newSplitPane: Pane = {
31
+ id: activePaneId,
32
+ type: 'splitPane',
33
+ orientation: 'horizontal',
34
+ children: [newLeafPane1, newLeafPane2],
35
+ };
36
+
37
+ const updatedPane = updatePane({
38
+ pane: state.pane,
39
+ activePaneId,
40
+ newTabList: undefined,
41
+ newActiveFileId: undefined,
42
+ });
43
+
44
+ const updateSplitPane = (pane: Pane, id: PaneId): Pane =>
45
+ pane.id === id
46
+ ? newSplitPane
47
+ : pane.type === 'splitPane'
48
+ ? {
49
+ ...pane,
50
+ children: pane.children.map((child) =>
51
+ updateSplitPane(child, id),
52
+ ),
53
+ }
54
+ : pane;
55
+
56
+ const finalPane = updateSplitPane(
57
+ updatedPane,
58
+ activePaneId,
59
+ );
60
+
61
+ return {
62
+ ...state,
63
+ pane: finalPane,
64
+ activePaneId: newLeafPane1.id,
65
+ };
66
+ };
@@ -0,0 +1,30 @@
1
+ import { VZAction, VZState } from '.';
2
+
3
+ export const updatePresenceIndicatorReducer = (
4
+ state: VZState,
5
+ action: VZAction,
6
+ ): VZState => {
7
+ if (action.type === 'update_presence_indicator') {
8
+ // True if there's already an entry for this user.
9
+ const needsUpdate =
10
+ state.sidebarPresenceIndicators.find(
11
+ (d) =>
12
+ d.username === action.presenceIndicator.username,
13
+ );
14
+
15
+ return {
16
+ ...state,
17
+ sidebarPresenceIndicators: needsUpdate
18
+ ? state.sidebarPresenceIndicators.map((d) =>
19
+ d.username === action.presenceIndicator.username
20
+ ? action.presenceIndicator
21
+ : d,
22
+ )
23
+ : [
24
+ ...state.sidebarPresenceIndicators,
25
+ action.presenceIndicator,
26
+ ],
27
+ };
28
+ }
29
+ return state;
30
+ };
package/src/types.ts CHANGED
@@ -192,13 +192,36 @@ export type VZCodeContent = {
192
192
  isInteracting?: boolean;
193
193
  };
194
194
  // Example Presence object, from ShareDB:
195
- // {"start":["files","69064344","text",183],"end":["files","69064344","text",183],"username":"Jim"}
195
+ // {
196
+ // "start": [
197
+ // "files",
198
+ // "71898298",
199
+ // "text",
200
+ // 415
201
+ // ],
202
+ // "end": [
203
+ // "files",
204
+ // "71898298",
205
+ // "text",
206
+ // 415
207
+ // ],
208
+ // "username": "Tim"
209
+ // }
196
210
  export type Presence = {
197
211
  start: Array<string | number>;
198
212
  end: Array<string | number>;
199
213
  username: Username;
200
214
  };
201
215
 
216
+ // An item in the list of sidebar presence indicators.
217
+ // It needs to know:
218
+ // * What user the presence is associated with
219
+ // * What file the presence is associated with
220
+ export type PresenceIndicator = {
221
+ username: Username;
222
+ fileId: FileId;
223
+ };
224
+
202
225
  // An id used for presence.
203
226
  export type PresenceId = string;
204
227