feat(settings): add beforeSave check (#161)

This commit is contained in:
megumin 2022-10-25 18:49:50 +01:00 committed by GitHub
parent e06ba68c40
commit 5e7c155f6e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 23 deletions

@ -67,6 +67,7 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
const [tempSettings, setTempSettings] = React.useState<Record<string, any>>({}); const [tempSettings, setTempSettings] = React.useState<Record<string, any>>({});
const [errors, setErrors] = React.useState<Record<string, boolean>>({}); const [errors, setErrors] = React.useState<Record<string, boolean>>({});
const [saveError, setSaveError] = React.useState<string | null>(null);
const canSubmit = () => Object.values(errors).every(e => !e); const canSubmit = () => Object.values(errors).every(e => !e);
@ -79,11 +80,20 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
})(); })();
}, []); }, []);
function saveAndClose() { async function saveAndClose() {
if (!plugin.options) { if (!plugin.options) {
onClose(); onClose();
return; return;
} }
if (plugin.beforeSave) {
const result = await Promise.resolve(plugin.beforeSave(tempSettings));
if (result !== true) {
setSaveError(result);
return;
}
}
let restartNeeded = false; let restartNeeded = false;
for (const [key, value] of Object.entries(tempSettings)) { for (const [key, value] of Object.entries(tempSettings)) {
const option = plugin.options[key]; const option = plugin.options[key];
@ -195,7 +205,8 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
</Forms.FormSection> </Forms.FormSection>
</ModalContent> </ModalContent>
<ModalFooter> <ModalFooter>
<Flex> <Flex flexDirection="column" style={{ width: "100%" }}>
<Flex style={{ marginLeft: "auto" }}>
<Button <Button
onClick={onClose} onClick={onClose}
size={Button.Sizes.SMALL} size={Button.Sizes.SMALL}
@ -218,6 +229,8 @@ export default function PluginModal({ plugin, onRestartNeeded, onClose, transiti
)} )}
</Tooltip> </Tooltip>
</Flex> </Flex>
{saveError && <Text variant="text-md/semibold" style={{ color: "var(--text-danger)" }}>Error while saving: {saveError}</Text>}
</Flex>
</ModalFooter> </ModalFooter>
</ModalRoot> </ModalRoot>
); );

@ -16,6 +16,8 @@
* along with this program. If not, see <https://www.gnu.org/licenses/>. * along with this program. If not, see <https://www.gnu.org/licenses/>.
*/ */
import { Promisable } from "type-fest";
import { Command } from "../api/Commands"; import { Command } from "../api/Commands";
// exists to export default definePlugin({...}) // exists to export default definePlugin({...})
@ -75,6 +77,11 @@ interface PluginDef {
* Optionally provide settings that the user can configure in the Plugins tab of settings. * Optionally provide settings that the user can configure in the Plugins tab of settings.
*/ */
options?: Record<string, PluginOptionsItem>; options?: Record<string, PluginOptionsItem>;
/**
* Check that this returns true before allowing a save to complete.
* If a string is returned, show the error to the user.
*/
beforeSave?(options: Record<string, any>): Promisable<true | string>;
/** /**
* Allows you to specify a custom Component that will be rendered in your * Allows you to specify a custom Component that will be rendered in your
* plugin's settings page * plugin's settings page