fileStorage: add rename file actions

This commit is contained in:
David Lechner
2022-03-12 14:18:02 -06:00
parent 7c0de33cfc
commit 33974c52b3
3 changed files with 102 additions and 0 deletions
+41
View File
@@ -109,6 +109,47 @@ export const fileStorageDidFailToDeleteFile = createAction(
}),
);
/**
* Requests for a file to be renamed.
* @param oldName The name of a file that exists in storage.
* @param newName The new name for the file.
*/
export const fileStorageRenameFile = createAction(
(oldName: string, newName: string) => ({
type: 'fileStorage.action.renameFile',
oldName,
newName,
}),
);
/**
* Indicates that fileStorageRenameFile(oldName, newName) succeeded.
* @param oldName The previous file name.
* @param newName The current file name.
*/
export const fileStorageDidRenameFile = createAction(
(oldName: string, newName: string) => ({
type: 'fileStorage.action.didRenameFile',
oldName,
newName,
}),
);
/**
* Indicates that fileStorageRenameFile(oldName, newName) failed.
* @param oldName The current file name.
* @param newName The requested new file name.
* @param error The error.
*/
export const fileStorageDidFailToRenameFile = createAction(
(oldName: string, newName: string, error: Error) => ({
type: 'fileStorage.action.didRenameFile',
oldName,
newName,
error,
}),
);
/**
* Request to export (download) a file.
* @param fileName The name of the file.
+25
View File
@@ -17,9 +17,11 @@ import {
fileStorageDidInitialize,
fileStorageDidReadFile,
fileStorageDidRemoveItem,
fileStorageDidRenameFile,
fileStorageDidWriteFile,
fileStorageExportFile,
fileStorageReadFile,
fileStorageRenameFile,
fileStorageWriteFile,
} from './actions';
import fileStorage from './sagas';
@@ -136,6 +138,29 @@ it('should delete files', async () => {
await saga.end();
});
describe('rename', () => {
it('should rename files', async () => {
const newName = 'new.file';
const saga = new AsyncSaga(fileStorage);
const [testFileName] = await setUpTestFile(saga);
saga.put(fileStorageRenameFile(testFileName, newName));
const action = await saga.take();
expect(action).toEqual(fileStorageDidChangeItem(newName));
const action2 = await saga.take();
expect(action2).toEqual(fileStorageDidRemoveItem(testFileName));
const action3 = await saga.take();
expect(action3).toEqual(fileStorageDidRenameFile(testFileName, newName));
await saga.end();
});
});
describe('export', () => {
it('should fail if file does not exist', async () => {
const testFileName = 'test.file';
+36
View File
@@ -23,13 +23,16 @@ import {
fileStorageDidFailToExportFile,
fileStorageDidFailToInitialize,
fileStorageDidFailToReadFile,
fileStorageDidFailToRenameFile,
fileStorageDidFailToWriteFile,
fileStorageDidInitialize,
fileStorageDidReadFile,
fileStorageDidRemoveItem,
fileStorageDidRenameFile,
fileStorageDidWriteFile,
fileStorageExportFile,
fileStorageReadFile,
fileStorageRenameFile,
fileStorageWriteFile,
} from './actions';
@@ -167,6 +170,38 @@ function* handleDeleteFile(
}
}
/**
* Renames a file in storage.
* @param files The localForage instance.
* @param action The action that triggered this saga.
*/
function* handleRenameFile(
files: LocalForage,
action: ReturnType<typeof fileStorageRenameFile>,
) {
try {
yield* call(async () => {
// There is no move/rename API, so we have to make a copy with the
// new name and delete the old one.
// FIXME: This should be an atomic operation, e.g. if removing the
// old file fails, the new file should be removed.
const contents = await files.getItem(action.oldName);
await files.setItem(action.newName, contents);
await files.removeItem(action.oldName);
});
yield* put(fileStorageDidRenameFile(action.oldName, action.newName));
} catch (err) {
yield* put(
fileStorageDidFailToRenameFile(
action.oldName,
action.newName,
ensureError(err),
),
);
}
}
function* handleArchiveAllFiles(files: LocalForage): Generator {
try {
const zip = new JSZip();
@@ -264,6 +299,7 @@ function* initialize(): Generator {
yield* takeEvery(fileStorageReadFile, handleReadFile, files);
yield* takeEvery(fileStorageWriteFile, handleWriteFile, files);
yield* takeEvery(fileStorageDeleteFile, handleDeleteFile, files);
yield* takeEvery(fileStorageRenameFile, handleRenameFile, files);
yield* takeEvery(fileStorageExportFile, handleExportFile, files);
yield* takeEvery(fileStorageArchiveAllFiles, handleArchiveAllFiles, files);