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
|
@ -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