Skip to content

Commit

Permalink
feature(collaboration) Support images and assets in collaboration. (#…
Browse files Browse the repository at this point in the history
…4799)

- Added `fromCollaboration` property to `UpdateFile` action.
- `applyFileChangeToMap` extended to include `IMAGE_FILE` and `ASSET_FILE`
  handling.
- Added `clearIfNotExpectedType` utility function.
- Added functions for populating the project contents map from `ImageFile`
  or `AssetFile` values.
- Added functions for creating `EditorAction` values from the yjs
  representation.
- Extended `CollabFile` to include union cases of `CollabImageFile`
  and `CollabAssetFile`.
- Changed `gatedActions` to check the `fromCollaboration` property of
  `UPDATE_FILE` actions.
- Modified `updateFileIfPossible` to prevent infinite looping of image
  and asset file updates.
  • Loading branch information
seanparsons authored Jan 29, 2024
1 parent 9513ea8 commit f2fe68c
Show file tree
Hide file tree
Showing 7 changed files with 357 additions and 83 deletions.
1 change: 1 addition & 0 deletions editor/src/components/editor/action-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -607,6 +607,7 @@ export interface UpdateFile {
filePath: string
file: ProjectFile
addIfNotInFiles: boolean
fromCollaboration: boolean
}

export interface UpdateProjectContents {
Expand Down
15 changes: 15 additions & 0 deletions editor/src/components/editor/actions/action-creators.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,21 @@ export function updateFile(
filePath: filePath,
file: file,
addIfNotInFiles: addIfNotInFiles,
fromCollaboration: false,
}
}

export function updateFileFromCollaboration(
filePath: string,
file: ProjectFile,
addIfNotInFiles: boolean,
): UpdateFile {
return {
action: 'UPDATE_FILE',
filePath: filePath,
file: file,
addIfNotInFiles: addIfNotInFiles,
fromCollaboration: true,
}
}

Expand Down
77 changes: 76 additions & 1 deletion editor/src/components/editor/store/collaborative-editing.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { setFeatureForUnitTestsUseInDescribeBlockOnly, wait } from '../../../uti
import { Y } from '../../../core/shared/yjs'
import {
RevisionsState,
assetFile,
imageFile,
isParseSuccess,
textFile,
textFileContents,
Expand All @@ -20,6 +22,8 @@ import { testParseCode } from '../../../core/workers/parser-printer/parser-print
import {
deleteFileFromCollaboration,
updateExportsDetailFromCollaborationUpdate,
updateFile,
updateFileFromCollaboration,
updateImportsFromCollaborationUpdate,
updateTopLevelElementsFromCollaborationUpdate,
} from '../actions/action-creators'
Expand Down Expand Up @@ -75,7 +79,7 @@ async function runAddHookForProjectChangesTest(test: AddHookForProjectChangesTes
Y.applyUpdate(secondCollaborationSession.mergeDoc, update)
})
// Updates to the second doc should be applied to the first doc.
// Currently this includes updates from everywhere, including itsef.
// Currently this includes updates from everywhere, including itself.
secondCollaborationSession.mergeDoc.on('update', (update) => {
Y.applyUpdate(firstCollaborationSession.mergeDoc, update)
})
Expand Down Expand Up @@ -147,6 +151,77 @@ describe('addHookForProjectChanges', () => {
})
})

it('adding image causes it to be added to the project contents', async () => {
const newFile = imageFile('jpg', undefined, 640, 480, 58345987345, undefined)
await runAddHookForProjectChangesTest({
initialState: {},
changesToApply: (firstSession, secondSession) => {
const updatedProjectContents = addFileToProjectContents({}, '/assets/test1.jpg', newFile)
const collaborationChanges = collateCollaborativeProjectChanges({}, updatedProjectContents)
updateCollaborativeProjectContents(firstSession, collaborationChanges, [])
},
expectations: (firstSessionPromises, secondSessionPromises) => {
expect(secondSessionPromises).toEqual([
updateFileFromCollaboration('/assets/test1.jpg', newFile, true),
])
},
})
})

it('adding image does not get added to the project contents if it includes the binary contents', async () => {
const newFile = imageFile(
'jpg',
'84395834543hj5h4kjh5j43h5dfgdfgd',
640,
480,
58345987345,
undefined,
)
await runAddHookForProjectChangesTest({
initialState: {},
changesToApply: (firstSession, secondSession) => {
const updatedProjectContents = addFileToProjectContents({}, '/assets/test1.jpg', newFile)
const collaborationChanges = collateCollaborativeProjectChanges({}, updatedProjectContents)
updateCollaborativeProjectContents(firstSession, collaborationChanges, [])
},
expectations: (firstSessionPromises, secondSessionPromises) => {
expect(secondSessionPromises).toEqual([])
},
})
})

it('adding asset causes it to be added to the project contents', async () => {
const newFile = assetFile(undefined, '01189998819991197253')
await runAddHookForProjectChangesTest({
initialState: {},
changesToApply: (firstSession, secondSession) => {
const updatedProjectContents = addFileToProjectContents({}, '/assets/test1.ttf', newFile)
const collaborationChanges = collateCollaborativeProjectChanges({}, updatedProjectContents)
updateCollaborativeProjectContents(firstSession, collaborationChanges, [])
},
expectations: (firstSessionPromises, secondSessionPromises) => {
expect(secondSessionPromises).toEqual([
updateFileFromCollaboration('/assets/test1.ttf', newFile, true),
])
},
})
})

it('adding asset does not get added to the project contents if it includes the binary contents', async () => {
const newFile = assetFile('aaaaaaaabbbbbbbcccccccccccc', '01189998819991197253')
await runAddHookForProjectChangesTest({
initialState: {},
changesToApply: (firstSession, secondSession) => {
const updatedProjectContents = addFileToProjectContents({}, '/assets/test1.ttf', newFile)
const collaborationChanges = collateCollaborativeProjectChanges({}, updatedProjectContents)
updateCollaborativeProjectContents(firstSession, collaborationChanges, [])
},
expectations: (firstSessionPromises, secondSessionPromises) => {
expect(secondSessionPromises).toEqual([])
},
})
})

it('adding file causes it to be added to the project contents, unless the file was modified by another user', async () => {
const code = 'export const A = <div />'
const newParsedCode = testParseCode(code)
Expand Down
Loading

0 comments on commit f2fe68c

Please sign in to comment.