Improve error handling
All checks were successful
Build on Push and create Release on Tag / build (push) Successful in 1m40s
All checks were successful
Build on Push and create Release on Tag / build (push) Successful in 1m40s
This commit is contained in:
parent
05984a8913
commit
eaf4a8e39e
7 changed files with 109 additions and 45 deletions
|
@ -3,12 +3,14 @@
|
|||
"editWhiteboard": "Edit whiteboard",
|
||||
"editShortcut": "Edit selected whiteboard",
|
||||
"errNoFileID": "File ID missing - couldn't open file.",
|
||||
"errNotAWhiteboard": "You must select a whiteboard, not a regular image.",
|
||||
"errNotAWhiteboard": "You must select a whiteboard, not a regular image. <a href='https://s.massive.box/jsdraw-plugin-instructions'>Usage instructions</a>",
|
||||
"errSyncIDNotFound": "Couldn't find SyncID in document for drawing, make sure you're trying to edit a whiteboard that is included in at least a note.",
|
||||
"errCreateUnknown": "Unknown error while creating editor, please try again.",
|
||||
"errInvalidBackgroundColor": "Invalid background color! Please enter an HEX color, like #000000 (black) or #FFFFFF (white). The old background color will be used.",
|
||||
"msgMustSelect": "Select a whiteboard in your document by left-clicking it, then use this icon/shortcut to open the editor directly.",
|
||||
"usageInstructionsLink": " <a href='https://s.massive.box/jsdraw-plugin-instructions'>Usage instructions</a>",
|
||||
"errMultipleSyncIDs": "Multiple syncIDs found in documents. Remove the drawings that don't exist from your documents.\n Sync conflict copies can cause this error, so make sure to delete them.\nFile IDs (the part you can change in the Rename menu) must be unique across all documents.\n<a href='https://git.massive.box/massivebox/siyuan-jsdraw-plugin/wiki/Errors-and-Fixes#multiple-syncids-found'>Full explanation</a>",
|
||||
"errUnchangedProtyle": "Make sure the image you're trying to edit still exists in your documents.",
|
||||
"errSaveGeneric": "Error saving! The current drawing has been copied to your clipboard. You may need to create a new drawing and paste it there.",
|
||||
"errMustSelect": "Select a whiteboard in your document by left-clicking it, then use this icon/shortcut to open the editor directly. <a href='https://s.massive.box/jsdraw-plugin-instructions'>Usage instructions</a>",
|
||||
"whiteboard": "Whiteboard",
|
||||
"settings": {
|
||||
"name": "js-draw Plugin Settings",
|
||||
|
|
|
@ -1,8 +1,9 @@
|
|||
import {PluginFile} from "@/file";
|
||||
import {CONFIG_FILENAME, JSON_MIME, STORAGE_PATH} from "@/const";
|
||||
import {Plugin, showMessage} from "siyuan";
|
||||
import {Plugin} from "siyuan";
|
||||
import {SettingUtils} from "@/libs/setting-utils";
|
||||
import {getFirstDefined} from "@/helper";
|
||||
import {ErrorReporter, InvalidBackgroundColorError} from "@/errors";
|
||||
|
||||
export interface Options {
|
||||
dialogOnDesktop: boolean
|
||||
|
@ -90,7 +91,7 @@ export class PluginConfigViewer {
|
|||
|
||||
let color = data.backgroundDropdown === "CUSTOM" ? data.background : data.backgroundDropdown;
|
||||
if(!PluginConfig.validateColor(color)) {
|
||||
showMessage(this.plugin.i18n.errInvalidBackgroundColor, 0, 'error');
|
||||
ErrorReporter.error(new InvalidBackgroundColorError());
|
||||
data.background = this.config.options.editorOptions.background;
|
||||
this.settingUtils.set('background', data.background);
|
||||
}
|
||||
|
|
|
@ -10,12 +10,16 @@ import Editor, {
|
|||
Vec2,
|
||||
Viewport
|
||||
} from "js-draw";
|
||||
import {Dialog, getFrontend, openTab, Plugin, showMessage} from "siyuan";
|
||||
import {Dialog, getFrontend, openTab, Plugin} from "siyuan";
|
||||
import {findSyncIDInProtyle, replaceSyncID} from "@/protyle";
|
||||
import DrawJSPlugin from "@/index";
|
||||
import {EditorOptions} from "@/config";
|
||||
import 'js-draw/styles';
|
||||
import {SyncIDNotFoundError, UnchangedProtyleError} from "@/errors";
|
||||
import {
|
||||
ErrorReporter,
|
||||
GenericSaveError, InternationalizedError, NoFileIDError, SyncIDNotFoundError,
|
||||
UnchangedProtyleError
|
||||
} from "@/errors";
|
||||
|
||||
export class PluginEditor {
|
||||
|
||||
|
@ -65,7 +69,7 @@ export class PluginEditor {
|
|||
let syncID = await findSyncIDInProtyle(fileID);
|
||||
|
||||
if(syncID == null) {
|
||||
throw new SyncIDNotFoundError(fileID);
|
||||
throw new SyncIDNotFoundError();
|
||||
}
|
||||
instance.setSyncID(syncID);
|
||||
await instance.restoreOrInitFile(defaultEditorOptions);
|
||||
|
@ -157,12 +161,13 @@ export class PluginEditor {
|
|||
saveButton.setDisabled(false);
|
||||
}, 500);
|
||||
} catch (error) {
|
||||
showMessage("Error saving! The current drawing has been copied to your clipboard. You may need to create a new drawing and paste it there.", 0, 'error');
|
||||
if(error instanceof UnchangedProtyleError) {
|
||||
showMessage("Make sure the image you're trying to edit still exists in your documents.", 0, 'error');
|
||||
if(error instanceof InternationalizedError) {
|
||||
ErrorReporter.error(error);
|
||||
}else{
|
||||
ErrorReporter.error(new GenericSaveError());
|
||||
console.error(error);
|
||||
}
|
||||
await navigator.clipboard.writeText(svgElem.outerHTML);
|
||||
console.error(error);
|
||||
console.log("Couldn't save SVG: ", svgElem.outerHTML)
|
||||
return;
|
||||
}
|
||||
|
@ -184,7 +189,7 @@ export class EditorManager {
|
|||
let editor = await PluginEditor.create(fileID, p.config.options.editorOptions);
|
||||
instance.setEditor(editor);
|
||||
}catch (error) {
|
||||
EditorManager.handleCreationError(error, p);
|
||||
ErrorReporter.error(error);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
@ -195,28 +200,19 @@ export class EditorManager {
|
|||
async init() {
|
||||
const fileID = this.data.fileID;
|
||||
if (fileID == null) {
|
||||
alert(p.i18n.errNoFileID);
|
||||
ErrorReporter.error(new NoFileIDError());
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const editor = await PluginEditor.create(fileID, p.config.options.editorOptions);
|
||||
this.element.appendChild(editor.getElement());
|
||||
}catch (error){
|
||||
EditorManager.handleCreationError(error, p);
|
||||
ErrorReporter.error(error);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
static handleCreationError(error: any, p: DrawJSPlugin) {
|
||||
console.error(error);
|
||||
let errorTxt = p.i18n.errCreateUnknown;
|
||||
if(error instanceof SyncIDNotFoundError) {
|
||||
errorTxt = p.i18n.errSyncIDNotFound;
|
||||
}
|
||||
showMessage(errorTxt, 0, 'error');
|
||||
}
|
||||
|
||||
toTab(p: Plugin) {
|
||||
openTab({
|
||||
app: p.app,
|
||||
|
|
|
@ -1,12 +1,80 @@
|
|||
import {showMessage} from "siyuan";
|
||||
|
||||
export class SyncIDNotFoundError extends Error {
|
||||
readonly fileID: string;
|
||||
export class InternationalizedError extends Error {
|
||||
readonly key: string;
|
||||
|
||||
constructor(fileID: string) {
|
||||
super(`SyncID not found for file ${fileID}`);
|
||||
this.fileID = fileID;
|
||||
Object.setPrototypeOf(this, new.target.prototype);
|
||||
constructor(key: string) {
|
||||
super(key);
|
||||
this.key = key;
|
||||
}
|
||||
}
|
||||
|
||||
export class UnchangedProtyleError extends Error {}
|
||||
export class ErrorReporter {
|
||||
|
||||
static i18n: any;
|
||||
|
||||
constructor(i18n: any) {
|
||||
ErrorReporter.i18n = i18n;
|
||||
}
|
||||
|
||||
static error(err: Error, timeout?: number) {
|
||||
console.error(err);
|
||||
let errorTxt = err.message;
|
||||
if(err instanceof InternationalizedError) {
|
||||
errorTxt = ErrorReporter.i18n[err.key];
|
||||
}
|
||||
if(!timeout) {
|
||||
timeout = 0;
|
||||
}
|
||||
showMessage(errorTxt, timeout, 'error');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export class SyncIDNotFoundError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errSyncIDNotFound');
|
||||
}
|
||||
}
|
||||
|
||||
export class UnchangedProtyleError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errUnchangedProtyle');
|
||||
}
|
||||
}
|
||||
|
||||
export class MultipleSyncIDsError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errMultipleSyncIDs');
|
||||
}
|
||||
}
|
||||
|
||||
export class GenericSaveError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errSaveGeneric');
|
||||
}
|
||||
}
|
||||
|
||||
export class NotAWhiteboardError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errNotAWhiteboard');
|
||||
}
|
||||
}
|
||||
|
||||
export class InvalidBackgroundColorError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errInvalidBackgroundColor');
|
||||
}
|
||||
}
|
||||
|
||||
export class NoFileIDError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errNoFileID');
|
||||
}
|
||||
}
|
||||
|
||||
export class MustSelectError extends InternationalizedError {
|
||||
constructor() {
|
||||
super('errMustSelect');
|
||||
}
|
||||
}
|
|
@ -52,7 +52,7 @@ abstract class PluginFileBase {
|
|||
protected toFile(customFilename?: string): File {
|
||||
let filename = customFilename || this.fileName;
|
||||
const blob = new Blob([this.content], { type: this.mimeType });
|
||||
return new File([blob], filename, { type: this.mimeType });
|
||||
return new File([blob], filename, { type: this.mimeType, lastModified: Date.now() });
|
||||
}
|
||||
|
||||
}
|
||||
|
|
14
src/index.ts
14
src/index.ts
|
@ -1,4 +1,4 @@
|
|||
import {Plugin, Protyle, showMessage} from 'siyuan';
|
||||
import {Plugin, Protyle} from 'siyuan';
|
||||
import {
|
||||
getMarkdownBlock,
|
||||
loadIcons,
|
||||
|
@ -10,6 +10,7 @@ import {migrate} from "@/migration";
|
|||
import {EditorManager} from "@/editor";
|
||||
import {PluginConfig, PluginConfigViewer} from "@/config";
|
||||
import {Analytics} from "@/analytics";
|
||||
import {ErrorReporter, MustSelectError, NotAWhiteboardError} from "@/errors";
|
||||
|
||||
export default class DrawJSPlugin extends Plugin {
|
||||
|
||||
|
@ -18,6 +19,7 @@ export default class DrawJSPlugin extends Plugin {
|
|||
|
||||
async onload() {
|
||||
|
||||
new ErrorReporter(this.i18n);
|
||||
loadIcons(this);
|
||||
EditorManager.registerTab(this);
|
||||
migrate()
|
||||
|
@ -55,7 +57,7 @@ export default class DrawJSPlugin extends Plugin {
|
|||
langKey: "editShortcut",
|
||||
hotkey: "⌥⇧D",
|
||||
callback: async () => {
|
||||
await this.editSelectedImg();
|
||||
this.editSelectedImg().catch(e => ErrorReporter.error(e, 5000));
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -63,7 +65,7 @@ export default class DrawJSPlugin extends Plugin {
|
|||
icon: "iconDraw",
|
||||
title: this.i18n.editShortcut,
|
||||
callback: async () => {
|
||||
await this.editSelectedImg();
|
||||
await this.editSelectedImg().catch(e => ErrorReporter.error(e, 5000));
|
||||
},
|
||||
position: "left"
|
||||
})
|
||||
|
@ -82,14 +84,12 @@ export default class DrawJSPlugin extends Plugin {
|
|||
|
||||
let selectedImg = document.getElementsByClassName('img--select');
|
||||
if(selectedImg.length == 0) {
|
||||
showMessage(this.i18n.msgMustSelect + this.i18n.usageInstructionsLink, 5000, 'info');
|
||||
return;
|
||||
throw new MustSelectError();
|
||||
}
|
||||
|
||||
let ids = imgSrcToIDs(findImgSrc(selectedImg[0] as HTMLElement));
|
||||
if(ids == null) {
|
||||
showMessage(this.i18n.errNotAWhiteboard + + this.i18n.usageInstructionsLink, 5000, 'error');
|
||||
return;
|
||||
throw new NotAWhiteboardError();
|
||||
}
|
||||
void this.analytics.sendEvent('edit');
|
||||
(await EditorManager.create(ids.fileID, this)).open(this);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import {getBlockByID, sql, updateBlock} from "@/api";
|
||||
import {assetPathToIDs, IDsToAssetPath} from "@/helper";
|
||||
import {MultipleSyncIDsError} from "@/errors";
|
||||
|
||||
export async function findSyncIDInProtyle(fileID: string, iter?: number): Promise<string> {
|
||||
|
||||
|
@ -15,11 +16,7 @@ export async function findSyncIDInProtyle(fileID: string, iter?: number): Promis
|
|||
if(syncID == null) {
|
||||
syncID = ids.syncID;
|
||||
}else if(ids.syncID !== syncID) {
|
||||
throw new Error(
|
||||
"Multiple syncIDs found in documents. Remove the drawings that don't exist from your documents.\n" +
|
||||
"Sync conflict copies can cause this error, so make sure to delete them, or at least the js-draw drawings they contain.\n" +
|
||||
"File IDs must be unique. Close this editor tab now."
|
||||
);
|
||||
throw new MultipleSyncIDsError();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -82,7 +79,7 @@ export async function replaceBlockContent(
|
|||
}
|
||||
|
||||
function extractImageSourcesFromMarkdown(markdown: string, mustStartWith?: string) {
|
||||
const imageRegex = /!\[.*?\]\((.*?)\)/g; // only get images
|
||||
const imageRegex = /!\[.*?\]\(([^)\s]+)(?:\s+"[^"]+")?\)/g; // only get images
|
||||
return Array.from(markdown.matchAll(imageRegex))
|
||||
.map(match => match[1])
|
||||
.filter(source => source.startsWith(mustStartWith)) // discard other images
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue