mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-14 10:35:11 +00:00
fileStorage: add rename file actions
This commit is contained in:
@@ -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.
|
||||
|
||||
@@ -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';
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user