Files
pybricks-code/src/editor/sagas.ts
T
David Lechner e36a30de4c pybricksMicropython/lib: add module
This creates a new module for dealing with stuff specific to Pybricks
MicroPython.
2022-03-11 15:41:16 -06:00

84 lines
2.7 KiB
TypeScript

// SPDX-License-Identifier: MIT
// Copyright (c) 2020-2022 The Pybricks Authors
import FileSaver from 'file-saver';
import { call, getContext, put, takeEvery } from 'typed-redux-saga/macro';
import { pythonFileExtension, pythonFileMimeType } from '../pybricksMicropython/lib';
import { ensureError } from '../utils';
import { EditorType } from './Editor';
import { didFailToSaveAs, didSaveAs, open, saveAs } from './actions';
/**
* Partial saga context type for context used in the editor sagas.
*/
export type EditorSagaContext = { editor: EditorType };
const decoder = new TextDecoder();
function* handleOpen(action: ReturnType<typeof open>): Generator {
const editor = yield* getContext<EditorType>('editor');
// istanbul ignore next: it is a bug to dispatch this action with no current editor
if (editor === null) {
console.error('open: No current editor');
return;
}
const text = decoder.decode(action.data);
editor.setValue(text);
}
function* handleSaveAs(): Generator {
const editor = yield* getContext<EditorType>('editor');
// istanbul ignore next: it is a bug to dispatch this action with no current editor
if (editor === null) {
console.error('saveAs: No current editor');
return;
}
const data = editor.getValue();
const blob = new Blob([data], { type: `${pythonFileMimeType};charset=utf-8` });
if (window.showSaveFilePicker) {
// This uses https://wicg.github.io/file-system-access which is not
// available in all browsers
try {
const handle = yield* call(() =>
window.showSaveFilePicker({
suggestedName: 'main.py',
types: [
{
accept: { [pythonFileMimeType]: pythonFileExtension },
// TODO: translate description
description: 'Python Files',
},
],
}),
);
const writeable = yield* call(() => handle.createWritable());
yield* call(() => writeable.write(blob));
yield* call(() => writeable.close());
} catch (err) {
yield* put(didFailToSaveAs(ensureError(err)));
return;
}
} else {
// this is a fallback to use the standard browser download mechanism
try {
FileSaver.saveAs(blob, 'main.py');
} catch (err) {
yield* put(didFailToSaveAs(ensureError(err)));
return;
}
}
yield* put(didSaveAs());
}
export default function* (): Generator {
yield* takeEvery(open, handleOpen);
yield* takeEvery(saveAs, handleSaveAs);
}