-
Notifications
You must be signed in to change notification settings - Fork 65
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
fix: Make sure that the file has a path after the real-time update
Updating files in real time only returns the couchDB document, which has no path for files, only for folders. This commit adds a mechanism to make sure you have one before adding it to the cozy-client store. A file without a path creates problems during sharing checks, for example when moving a file.
- Loading branch information
Showing
3 changed files
with
134 additions
and
6 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,130 @@ | ||
import { memo, useEffect } from 'react' | ||
|
||
import { useClient, Mutations } from 'cozy-client' | ||
import { ensureFilePath } from 'cozy-client/dist/models/file' | ||
import { receiveMutationResult } from 'cozy-client/dist/store' | ||
|
||
import { buildFileByIdQuery } from 'modules/queries' | ||
|
||
/** | ||
* Normalizes an object representing a CouchDB document | ||
* | ||
* Ensures existence of `_type` | ||
* | ||
* @public | ||
* @param {CouchDBDocument} couchDBDoc - object representing the document | ||
* @returns {CozyClientDocument} full normalized document | ||
*/ | ||
const normalizeDoc = (couchDBDoc, doctype) => { | ||
return { | ||
id: couchDBDoc._id, | ||
_type: doctype, | ||
...couchDBDoc | ||
} | ||
} | ||
|
||
/** | ||
* DispatchChange | ||
* | ||
* @param {CozyClient} client CozyClient instane | ||
* @param {Doctype} doctype Doctype of the document to update | ||
* @param {CouchDBDocument} couchDBDoc Document to update | ||
* @param {Mutation} mutationDefinitionCreator Mutation to apply | ||
*/ | ||
const dispatchChange = ( | ||
client, | ||
doctype, | ||
couchDBDoc, | ||
mutationDefinitionCreator | ||
) => { | ||
const data = normalizeDoc(couchDBDoc, doctype) | ||
const response = { | ||
data | ||
} | ||
|
||
const options = {} | ||
client.dispatch( | ||
receiveMutationResult( | ||
client.generateRandomId(), | ||
response, | ||
options, | ||
mutationDefinitionCreator(data) | ||
) | ||
) | ||
} | ||
|
||
const ensureFileHasPath = async (doc, client) => { | ||
if (doc.path) return doc | ||
|
||
const parentQuery = buildFileByIdQuery(doc.dir_id) | ||
const parentResult = await client.fetchQueryAndGetFromState(parentQuery) | ||
|
||
return ensureFilePath(doc, parentResult.data) | ||
} | ||
|
||
/** | ||
* Component that subscribes to io.cozy.files document changes and keep the | ||
* internal store updated. This is a copy of RealTimeQueries from cozy-client | ||
* with a tweak to merge the changes with the existing document from the store. | ||
* You can have more detail on the problematic we are solving here: | ||
* https://github.com/cozy/cozy-client/issues/1412 | ||
* | ||
* @param {object} options - Options | ||
* @param {Doctype} options.doctype - The doctype to watch | ||
* @returns {null} The component does not display anything. | ||
*/ | ||
const FilesRealTimeQueries = ({ | ||
doctype = 'io.cozy.files', | ||
computeDocBeforeDispatchCreate = ensureFileHasPath, | ||
computeDocBeforeDispatchUpdate = ensureFileHasPath, | ||
computeDocBeforeDispatchDelete = (doc, client) => | ||
ensureFileHasPath({ ...doc, _deleted: true }, client) | ||
}) => { | ||
const client = useClient() | ||
|
||
useEffect(() => { | ||
const realtime = client.plugins.realtime | ||
|
||
if (!realtime) { | ||
throw new Error( | ||
'You must include the realtime plugin to use RealTimeQueries' | ||
) | ||
} | ||
|
||
const dispatchCreate = async couchDBDoc => { | ||
const doc = await computeDocBeforeDispatchCreate(couchDBDoc, client) | ||
dispatchChange(client, doctype, doc, Mutations.createDocument) | ||
} | ||
const dispatchUpdate = async couchDBDoc => { | ||
const doc = await computeDocBeforeDispatchUpdate(couchDBDoc, client) | ||
dispatchChange(client, doctype, doc, Mutations.updateDocument) | ||
} | ||
const dispatchDelete = async couchDBDoc => { | ||
const doc = await computeDocBeforeDispatchDelete(couchDBDoc, client) | ||
dispatchChange(client, doctype, doc, Mutations.deleteDocument) | ||
} | ||
|
||
const subscribe = async () => { | ||
await realtime.subscribe('created', doctype, dispatchCreate) | ||
await realtime.subscribe('updated', doctype, dispatchUpdate) | ||
await realtime.subscribe('deleted', doctype, dispatchDelete) | ||
} | ||
subscribe() | ||
|
||
return () => { | ||
realtime.unsubscribe('created', doctype, dispatchCreate) | ||
realtime.unsubscribe('updated', doctype, dispatchUpdate) | ||
realtime.unsubscribe('deleted', doctype, dispatchDelete) | ||
} | ||
}, [ | ||
client, | ||
computeDocBeforeDispatchCreate, | ||
computeDocBeforeDispatchDelete, | ||
computeDocBeforeDispatchUpdate, | ||
doctype | ||
]) | ||
|
||
return null | ||
} | ||
|
||
export default memo(FilesRealTimeQueries) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters