Skip to content

Commit 36cbc51

Browse files
committed
Allow following read-only users
1 parent 576c858 commit 36cbc51

File tree

9 files changed

+126
-60
lines changed

9 files changed

+126
-60
lines changed

packages/app/src/app/overmind/effects/live/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
Module,
55
RoomInfo,
66
UserViewRange,
7+
UserSelection,
78
} from '@codesandbox/common/lib/types';
89
import {
910
captureException,
@@ -519,7 +520,7 @@ class Live {
519520
sendUserSelection(
520521
moduleShortid: string | null,
521522
liveUserId: string,
522-
selection: any
523+
selection: UserSelection
523524
) {
524525
return this.send('user:selection', {
525526
liveUserId,

packages/app/src/app/overmind/effects/vscode/ModelsHandler.ts

Lines changed: 44 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,17 +336,50 @@ export class ModelsHandler {
336336
});
337337
}
338338

339+
private getSelectionDecorationId = (
340+
userId: string,
341+
modelId: string,
342+
shortid: string
343+
) => [userId, modelId, shortid].join('|');
344+
345+
private cleanUserSelections = (
346+
model: any,
347+
moduleShortid: string,
348+
userSelectionsToKeep: EditorSelection[]
349+
) => {
350+
const existingSelectionDecorations = Object.keys(
351+
this.userSelectionDecorations
352+
).filter(s => s.endsWith([model.id, moduleShortid].join('|')));
353+
354+
const newUserSelections = {};
355+
for (let i = 0; i < userSelectionsToKeep.length; i++) {
356+
newUserSelections[userSelectionsToKeep[i].userId] =
357+
userSelectionsToKeep[i];
358+
}
359+
360+
existingSelectionDecorations.forEach(existingDecorationId => {
361+
const userId = existingDecorationId.split('|')[0];
362+
if (!newUserSelections[userId]) {
363+
const decorationId = this.getSelectionDecorationId(
364+
userId,
365+
model.id,
366+
moduleShortid
367+
);
368+
this.userSelectionDecorations[decorationId] = model.deltaDecorations(
369+
this.userSelectionDecorations[decorationId] || [],
370+
[]
371+
);
372+
}
373+
});
374+
};
375+
339376
nameTagTimeouts: { [name: string]: number } = {};
340377

341378
public async updateUserSelections(
342379
module: Module,
343380
userSelections: EditorSelection[],
344381
showNameTag = true
345382
) {
346-
if (!this.moduleModels['/sandbox' + module.path]) {
347-
return;
348-
}
349-
350383
const moduleModel = this.getModuleModelByPath(module.path);
351384

352385
if (!moduleModel?.model) {
@@ -356,10 +389,16 @@ export class ModelsHandler {
356389
const model = await moduleModel.model;
357390
const lines = model.getLinesContent() || [];
358391

392+
this.cleanUserSelections(model, module.shortid, userSelections);
393+
359394
userSelections.forEach((data: EditorSelection) => {
360395
const { userId } = data;
361396

362-
const decorationId = userId + model.id + module.shortid;
397+
const decorationId = this.getSelectionDecorationId(
398+
userId,
399+
model.id,
400+
module.shortid
401+
);
363402
if (data.selection === null) {
364403
this.userSelectionDecorations[decorationId] = model.deltaDecorations(
365404
this.userSelectionDecorations[decorationId] || [],

packages/app/src/app/overmind/effects/vscode/index.ts

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -617,15 +617,17 @@ export class VSCodeEffect {
617617
if (activeEditor) {
618618
const model = activeEditor.getModel();
619619

620-
const lineColumnPos = indexToLineAndColumn(
621-
model.getLinesContent() || [],
622-
pos
623-
);
620+
if (model) {
621+
const lineColumnPos = indexToLineAndColumn(
622+
model.getLinesContent() || [],
623+
pos
624+
);
624625

625-
activeEditor.revealPositionInCenterIfOutsideViewport(
626-
lineColumnPos,
627-
scrollType
628-
);
626+
activeEditor.revealPositionInCenterIfOutsideViewport(
627+
lineColumnPos,
628+
scrollType
629+
);
630+
}
629631
}
630632
}
631633

packages/app/src/app/overmind/namespaces/editor/actions.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -519,10 +519,7 @@ export const moduleSelected: AsyncAction<
519519
await actions.editor.internal.setCurrentModule(module);
520520

521521
if (state.live.isLive && state.live.liveUser && state.live.roomInfo) {
522-
effects.vscode.updateUserSelections(
523-
module,
524-
actions.live.internal.getSelectionsForModule(module)
525-
);
522+
actions.editor.internal.updateSelectionsOfModule({ module });
526523
state.live.liveUser.currentModuleShortid = module.shortid;
527524

528525
if (state.live.followingUserId) {

packages/app/src/app/overmind/namespaces/editor/internalActions.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,16 @@ export const initializeLiveSandbox: AsyncAction<Sandbox> = async (
8181
}
8282
};
8383

84+
export const updateSelectionsOfModule: AsyncAction<{ module: Module }> = async (
85+
{ actions, effects },
86+
{ module }
87+
) => {
88+
effects.vscode.updateUserSelections(
89+
module,
90+
actions.live.internal.getSelectionsForModule(module)
91+
);
92+
};
93+
8494
export const setModuleSavedCode: Action<{
8595
moduleShortid: string;
8696
savedCode: string | null;

packages/app/src/app/overmind/namespaces/live/actions.ts

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
LiveMessage,
33
LiveMessageEvent,
44
UserViewRange,
5+
UserSelection,
56
} from '@codesandbox/common/lib/types';
67
import { Action, AsyncAction, Operator } from 'app/overmind';
78
import { withLoadApp } from 'app/overmind/factories';
@@ -184,15 +185,13 @@ export const sendCurrentSelection: Action = ({ state, effects }) => {
184185
return;
185186
}
186187

187-
if (state.live.isCurrentEditor) {
188-
const { liveUserId } = state.live;
189-
if (liveUserId) {
190-
effects.live.sendUserSelection(
191-
state.editor.currentModuleShortid,
192-
liveUserId,
193-
state.live.currentSelection
194-
);
195-
}
188+
const { liveUserId } = state.live;
189+
if (liveUserId) {
190+
effects.live.sendUserSelection(
191+
state.editor.currentModuleShortid,
192+
liveUserId,
193+
state.live.currentSelection
194+
);
196195
}
197196
};
198197

@@ -249,36 +248,32 @@ export const onViewRangeChanged: Action<UserViewRange> = (
249248
}
250249
};
251250

252-
export const onSelectionChanged: Action<any> = (
251+
export const onSelectionChanged: Action<UserSelection> = (
253252
{ state, effects },
254253
selection
255254
) => {
256255
if (!state.live.roomInfo) {
257256
return;
258257
}
259258

260-
if (state.live.isCurrentEditor) {
261-
const { liveUserId } = state.live;
262-
const moduleShortid = state.editor.currentModuleShortid;
263-
if (!moduleShortid || !liveUserId) {
264-
return;
265-
}
266-
267-
state.live.currentSelection = selection;
268-
const userIndex = state.live.roomInfo.users.findIndex(
269-
u => u.id === liveUserId
270-
);
259+
const { liveUserId } = state.live;
260+
const moduleShortid = state.editor.currentModuleShortid;
261+
if (!moduleShortid || !liveUserId) {
262+
return;
263+
}
271264

272-
if (userIndex > -1) {
273-
if (state.live.roomInfo.users[userIndex]) {
274-
state.live.roomInfo.users[
275-
userIndex
276-
].currentModuleShortid = moduleShortid;
265+
state.live.currentSelection = selection;
266+
const userIndex = state.live.roomInfo.users.findIndex(
267+
u => u.id === liveUserId
268+
);
277269

278-
state.live.roomInfo.users[userIndex].selection = selection;
270+
if (userIndex > -1) {
271+
const user = state.live.roomInfo.users[userIndex];
272+
if (user) {
273+
user.currentModuleShortid = moduleShortid;
274+
user.selection = selection;
279275

280-
effects.live.sendUserSelection(moduleShortid, liveUserId, selection);
281-
}
276+
effects.live.sendUserSelection(moduleShortid, liveUserId, selection);
282277
}
283278
}
284279
};
@@ -364,6 +359,13 @@ export const onFollow: Action<{
364359
effects.analytics.track('Follow Along in Live');
365360
state.live.followingUserId = liveUserId;
366361
actions.live.revealViewRange({ liveUserId });
362+
363+
if (state.editor.currentModule) {
364+
// In case the selections were hidden first
365+
actions.editor.internal.updateSelectionsOfModule({
366+
module: state.editor.currentModule,
367+
});
368+
}
367369
};
368370

369371
export const onUserLeft: Action<{
@@ -387,6 +389,13 @@ export const onStopFollow: Action = ({ state, effects, actions }) => {
387389
}
388390

389391
state.live.followingUserId = null;
392+
393+
if (state.editor.currentModule) {
394+
// In case the selections were hidden first
395+
actions.editor.internal.updateSelectionsOfModule({
396+
module: state.editor.currentModule,
397+
});
398+
}
390399
};
391400

392401
export const revealViewRange: Action<{ liveUserId: string }> = (

packages/app/src/app/overmind/namespaces/live/internalActions.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export const getSelectionsForModule: Action<Module, EditorSelection[]> = (
167167
if (
168168
userId === state.live.liveUserId ||
169169
user.currentModuleShortid !== moduleShortid ||
170-
!state.live.isEditor(userId)
170+
(!state.live.isEditor(userId) && state.live.followingUserId !== userId)
171171
) {
172172
return;
173173
}

packages/app/src/app/overmind/namespaces/live/liveMessageOperators.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ export const onUsersChanged: Operator<LiveMessage<{
6060
users: LiveUser[];
6161
editor_ids: string[];
6262
owner_ids: string[];
63-
}>> = mutate(({ state, effects, actions }, { data }) => {
63+
}>> = mutate(({ state, actions }, { data }) => {
6464
if (state.live.isLoading || !state.live.roomInfo || !state.live.isLive) {
6565
return;
6666
}
@@ -72,10 +72,9 @@ export const onUsersChanged: Operator<LiveMessage<{
7272
state.live.roomInfo.ownerIds = data.owner_ids;
7373

7474
if (state.editor.currentModule) {
75-
effects.vscode.updateUserSelections(
76-
state.editor.currentModule,
77-
actions.live.internal.getSelectionsForModule(state.editor.currentModule)
78-
);
75+
actions.editor.internal.updateSelectionsOfModule({
76+
module: state.editor.currentModule,
77+
});
7978
}
8079
});
8180

@@ -96,10 +95,9 @@ export const onUserEntered: Operator<LiveMessage<{
9695
state.live.roomInfo.ownerIds = data.owner_ids;
9796

9897
if (state.editor.currentModule) {
99-
effects.vscode.updateUserSelections(
100-
state.editor.currentModule,
101-
actions.live.internal.getSelectionsForModule(state.editor.currentModule)
102-
);
98+
actions.editor.internal.updateSelectionsOfModule({
99+
module: state.editor.currentModule,
100+
});
103101
}
104102

105103
// Send our own selections and viewranges to everyone, just to let the others know where
@@ -406,7 +404,13 @@ export const onUserSelection: Operator<LiveMessage<{
406404
const module = state.editor.currentSandbox.modules.find(
407405
m => m.shortid === moduleShortid
408406
);
409-
if (module && state.live.isEditor(userSelectionLiveUserId)) {
407+
408+
const isFollowingUser =
409+
state.live.followingUserId === userSelectionLiveUserId;
410+
if (
411+
module &&
412+
(state.live.isEditor(userSelectionLiveUserId) || isFollowingUser)
413+
) {
410414
const user = state.live.roomInfo.users.find(
411415
u => u.id === userSelectionLiveUserId
412416
);
@@ -421,7 +425,7 @@ export const onUserSelection: Operator<LiveMessage<{
421425
},
422426
]);
423427

424-
if (state.live.followingUserId === userSelectionLiveUserId) {
428+
if (isFollowingUser) {
425429
actions.live.revealCursorPosition({
426430
liveUserId: userSelectionLiveUserId,
427431
});

packages/app/src/app/overmind/utils/items.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,11 @@ export function getDisabledItems(store: any): INavigationItem[] {
8181
}
8282

8383
if (!currentSandbox.owned || !store.isLoggedIn) {
84-
return [GITHUB, DEPLOYMENT, LIVE];
84+
const returnedItems = [GITHUB, DEPLOYMENT];
85+
if (!store.live.isLive) {
86+
returnedItems.push(LIVE);
87+
}
88+
return returnedItems;
8589
}
8690

8791
return [];

0 commit comments

Comments
 (0)