@lvl99dotcom/paintcanvas 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/dist/lib/assets/index.d.ts +92 -0
- package/dist/lib/assets/index.js +106 -0
- package/dist/lib/assets/schema.d.ts +151 -0
- package/dist/lib/assets/schema.js +76 -0
- package/dist/lib/brushes/presetFile/index.d.ts +6 -27
- package/dist/lib/brushes/presetFile/index.js +34 -47
- package/dist/lib/brushes/types/index.d.ts +2 -11
- package/dist/lib/classes/AssetSync/index.d.ts +45 -0
- package/dist/lib/classes/AssetSync/index.js +80 -0
- package/dist/lib/classes/ColourPalettes/index.d.ts +83 -0
- package/dist/lib/classes/ColourPalettes/index.js +165 -0
- package/dist/lib/classes/CustomPresets/index.d.ts +14 -15
- package/dist/lib/classes/CustomPresets/index.js +25 -10
- package/dist/lib/classes/LayerAutosave/index.d.ts +9 -2
- package/dist/lib/classes/LayerAutosave/index.js +16 -6
- package/dist/lib/classes/PaintCanvas/index.d.ts +111 -23
- package/dist/lib/classes/PaintCanvas/index.js +219 -58
- package/dist/lib/classes/Palette/index.d.ts +3 -2
- package/dist/lib/classes/Palette/index.js +3 -2
- package/dist/lib/classes/ProfileGraphs/index.d.ts +13 -2
- package/dist/lib/classes/ProfileGraphs/index.js +22 -2
- package/dist/lib/classes/RemoteDocumentAutosave/index.d.ts +73 -0
- package/dist/lib/classes/RemoteDocumentAutosave/index.js +119 -0
- package/dist/lib/classes/SettingsAutosave/index.d.ts +7 -3
- package/dist/lib/classes/SettingsAutosave/index.js +28 -7
- package/dist/lib/classes/SettingsExtensions/index.d.ts +67 -0
- package/dist/lib/classes/SettingsExtensions/index.js +88 -0
- package/dist/lib/document/index.d.ts +61 -4
- package/dist/lib/document/index.js +173 -4
- package/dist/lib/document/schema.d.ts +154 -39
- package/dist/lib/document/schema.js +91 -25
- package/dist/lib/messages/schema.d.ts +176 -74
- package/dist/lib/messages/schema.js +2 -1
- package/dist/lib/palette/index.d.ts +8 -42
- package/dist/lib/palette/index.js +26 -59
- package/dist/lib/palette/schema.d.ts +111 -22
- package/dist/lib/palette/schema.js +51 -26
- package/dist/lib/presets/index.d.ts +1 -9
- package/dist/lib/presets/index.js +4 -10
- package/dist/lib/presets/schema.d.ts +118 -73
- package/dist/lib/presets/schema.js +28 -60
- package/dist/lib/profiles/profileFile/index.d.ts +10 -0
- package/dist/lib/profiles/profileFile/index.js +19 -0
- package/dist/lib/profiles/schema.d.ts +96 -3
- package/dist/lib/profiles/schema.js +31 -7
- package/dist/lib/schemas/index.d.ts +42 -0
- package/dist/lib/schemas/index.js +60 -0
- package/dist/lib/settings/index.d.ts +37 -22
- package/dist/lib/settings/index.js +78 -37
- package/dist/lib/settings/schema.d.ts +198 -76
- package/dist/lib/settings/schema.js +92 -86
- package/dist/lib/storage/index.d.ts +82 -3
- package/dist/lib/storage/index.js +82 -5
- package/dist/lib/validation/validators.generated.d.ts +19 -8
- package/dist/lib/validation/validators.generated.js +44716 -18900
- package/dist/lib/version/index.js +1 -1
- package/dist/locales/en-GB.js +23 -5
- package/dist/locales/en-US.js +23 -5
- package/dist/locales/fr.js +23 -5
- package/dist/locales/ja.js +23 -5
- package/dist/locales/ko.js +23 -5
- package/dist/locales/zh-Hans.js +23 -5
- package/dist/locales/zh-Hant.js +23 -5
- package/dist/package.js +1 -1
- package/dist/testing/app.d.ts +6 -2
- package/dist/testing/app.js +7 -2
- package/dist/testing/documentStore.d.ts +26 -0
- package/dist/testing/documentStore.js +31 -0
- package/dist/ui/elements/PaintCanvas/index.d.ts +6 -2
- package/dist/ui/elements/PaintCanvas/index.js +20 -6
- package/dist/ui/elements/PcAppSettings/index.d.ts +5 -6
- package/dist/ui/elements/PcAppSettings/index.js +17 -27
- package/dist/ui/elements/PcPanelBrushes/index.d.ts +1 -1
- package/dist/ui/elements/PcPanelBrushes/index.js +22 -28
- package/dist/ui/elements/PcPanelBrushes/style.js +1 -1
- package/dist/ui/elements/PcPanelColours/index.d.ts +56 -19
- package/dist/ui/elements/PcPanelColours/index.js +251 -104
- package/dist/ui/elements/PcPanelColours/style.js +1 -1
- package/dist/ui/elements/PcStats/index.d.ts +8 -4
- package/dist/ui/elements/PcStats/index.js +39 -5
- package/locales/en-GB.json +23 -5
- package/locales/en-US.json +23 -5
- package/locales/fr.json +23 -5
- package/locales/ja.json +23 -5
- package/locales/ko.json +23 -5
- package/locales/zh-Hans.json +23 -5
- package/locales/zh-Hant.json +23 -5
- package/package.json +2 -1
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
import { LOCALE_PATTERN, RENDERINGS, THEMES } from "../classes/UiSettings/index.js";
|
|
2
|
-
import { HEX_COLOUR_PATTERN,
|
|
2
|
+
import { HEX_COLOUR_PATTERN, colourPaletteSchema, paletteColoursSchema } from "../palette/schema.js";
|
|
3
3
|
import { profileGraphSchema } from "../profiles/schema.js";
|
|
4
|
+
import { MAX_PRESETS_PER_FILE, brushPresetSchema } from "../presets/schema.js";
|
|
5
|
+
import { fileSchemaUrlSchema } from "../assets/schema.js";
|
|
6
|
+
import { SCHEMA_DIALECT, schemaUrl } from "../schemas/index.js";
|
|
4
7
|
// src/lib/settings/schema.ts
|
|
5
|
-
/**
|
|
6
|
-
var
|
|
7
|
-
/**
|
|
8
|
-
var
|
|
9
|
-
/** The version of the settings file format */
|
|
10
|
-
var SETTINGS_FILE_VERSION = 1;
|
|
11
|
-
/** Longest settings file format name (characters) */
|
|
12
|
-
var MAX_SETTINGS_FILE_FORMAT_LENGTH = 100;
|
|
8
|
+
/** Version of the app settings schema */
|
|
9
|
+
var APP_SETTINGS_SCHEMA_VERSION = "1.0.0";
|
|
10
|
+
/** `@type` of an app settings file */
|
|
11
|
+
var APP_SETTINGS_TYPE = "PaintCanvas/AppSettings";
|
|
13
12
|
/** Most keyboard shortcuts in saved settings */
|
|
14
13
|
var MAX_SAVED_SHORTCUTS = 200;
|
|
15
14
|
/** A `#rrggbb` colour */
|
|
@@ -19,7 +18,6 @@ var hexColour = {
|
|
|
19
18
|
};
|
|
20
19
|
/** Schema of a key combination */
|
|
21
20
|
var keyComboSchema = {
|
|
22
|
-
$id: "paintcanvas/key-combo",
|
|
23
21
|
type: "object",
|
|
24
22
|
additionalProperties: false,
|
|
25
23
|
required: ["key"],
|
|
@@ -35,89 +33,97 @@ var keyComboSchema = {
|
|
|
35
33
|
alt: { type: "boolean" }
|
|
36
34
|
}
|
|
37
35
|
};
|
|
38
|
-
/**
|
|
36
|
+
/** Schemas of each part of the app settings PaintCanvas has */
|
|
37
|
+
var settingsProperties = {
|
|
38
|
+
input: {
|
|
39
|
+
type: "object",
|
|
40
|
+
additionalProperties: false,
|
|
41
|
+
properties: {
|
|
42
|
+
scrollPan: { type: "boolean" },
|
|
43
|
+
pinchZoom: { type: "boolean" },
|
|
44
|
+
modifierScrollZoom: { type: "boolean" },
|
|
45
|
+
focusPen: { type: "boolean" },
|
|
46
|
+
gestures: {
|
|
47
|
+
type: "object",
|
|
48
|
+
maxProperties: 20,
|
|
49
|
+
additionalProperties: {
|
|
50
|
+
type: "string",
|
|
51
|
+
maxLength: 50
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
shortcuts: {
|
|
57
|
+
type: "object",
|
|
58
|
+
maxProperties: 200,
|
|
59
|
+
propertyNames: { maxLength: 64 },
|
|
60
|
+
additionalProperties: { anyOf: [{ type: "null" }, keyComboSchema] }
|
|
61
|
+
},
|
|
62
|
+
palettes: {
|
|
63
|
+
type: "array",
|
|
64
|
+
maxItems: 100,
|
|
65
|
+
items: { $ref: colourPaletteSchema.$id }
|
|
66
|
+
},
|
|
67
|
+
colours: {
|
|
68
|
+
type: "object",
|
|
69
|
+
additionalProperties: false,
|
|
70
|
+
required: ["foreground", "background"],
|
|
71
|
+
properties: {
|
|
72
|
+
foreground: hexColour,
|
|
73
|
+
background: hexColour
|
|
74
|
+
}
|
|
75
|
+
},
|
|
76
|
+
profiles: {
|
|
77
|
+
type: "array",
|
|
78
|
+
maxItems: 100,
|
|
79
|
+
items: { $ref: profileGraphSchema.$id }
|
|
80
|
+
},
|
|
81
|
+
brushes: {
|
|
82
|
+
type: "array",
|
|
83
|
+
maxItems: MAX_PRESETS_PER_FILE,
|
|
84
|
+
items: { $ref: brushPresetSchema.$id }
|
|
85
|
+
},
|
|
86
|
+
ui: {
|
|
87
|
+
type: "object",
|
|
88
|
+
additionalProperties: false,
|
|
89
|
+
properties: {
|
|
90
|
+
theme: { enum: THEMES },
|
|
91
|
+
locale: {
|
|
92
|
+
type: "string",
|
|
93
|
+
minLength: 1,
|
|
94
|
+
maxLength: 35,
|
|
95
|
+
pattern: LOCALE_PATTERN
|
|
96
|
+
},
|
|
97
|
+
rendering: { enum: RENDERINGS }
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
/**
|
|
102
|
+
* Schema of the user's app settings as kept in the browser: parts PaintCanvas doesn't know are left for wrapper apps
|
|
103
|
+
* to check (see `SettingsExtension`), and colours older versions saved in PaintCanvas's palette (`palette`) are allowed.
|
|
104
|
+
*/
|
|
39
105
|
var settingsSchema = {
|
|
40
106
|
$id: "paintcanvas/settings",
|
|
41
107
|
type: "object",
|
|
42
|
-
additionalProperties: false,
|
|
43
108
|
properties: {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
additionalProperties: false,
|
|
47
|
-
properties: {
|
|
48
|
-
scrollPan: { type: "boolean" },
|
|
49
|
-
pinchZoom: { type: "boolean" },
|
|
50
|
-
modifierScrollZoom: { type: "boolean" },
|
|
51
|
-
focusPen: { type: "boolean" },
|
|
52
|
-
gestures: {
|
|
53
|
-
type: "object",
|
|
54
|
-
maxProperties: 20,
|
|
55
|
-
additionalProperties: {
|
|
56
|
-
type: "string",
|
|
57
|
-
maxLength: 50
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
},
|
|
62
|
-
shortcuts: {
|
|
63
|
-
type: "object",
|
|
64
|
-
maxProperties: 200,
|
|
65
|
-
propertyNames: { maxLength: 64 },
|
|
66
|
-
additionalProperties: { anyOf: [{ type: "null" }, { $ref: "key-combo" }] }
|
|
67
|
-
},
|
|
68
|
-
palette: {
|
|
69
|
-
type: "array",
|
|
70
|
-
maxItems: MAX_PALETTE_COLOURS,
|
|
71
|
-
items: paletteFileSchema.properties.colours.items
|
|
72
|
-
},
|
|
73
|
-
colours: {
|
|
74
|
-
type: "object",
|
|
75
|
-
additionalProperties: false,
|
|
76
|
-
required: ["foreground", "background"],
|
|
77
|
-
properties: {
|
|
78
|
-
foreground: hexColour,
|
|
79
|
-
background: hexColour
|
|
80
|
-
}
|
|
81
|
-
},
|
|
82
|
-
profiles: {
|
|
83
|
-
type: "array",
|
|
84
|
-
maxItems: 100,
|
|
85
|
-
items: profileGraphSchema
|
|
86
|
-
},
|
|
87
|
-
ui: {
|
|
88
|
-
type: "object",
|
|
89
|
-
additionalProperties: false,
|
|
90
|
-
properties: {
|
|
91
|
-
theme: { enum: THEMES },
|
|
92
|
-
locale: {
|
|
93
|
-
type: "string",
|
|
94
|
-
minLength: 1,
|
|
95
|
-
maxLength: 35,
|
|
96
|
-
pattern: LOCALE_PATTERN
|
|
97
|
-
},
|
|
98
|
-
rendering: { enum: RENDERINGS }
|
|
99
|
-
}
|
|
100
|
-
}
|
|
109
|
+
...settingsProperties,
|
|
110
|
+
palette: paletteColoursSchema
|
|
101
111
|
}
|
|
102
112
|
};
|
|
103
|
-
/**
|
|
104
|
-
|
|
105
|
-
|
|
113
|
+
/**
|
|
114
|
+
* Schema of an app settings file. Parts it doesn't name are added by wrapper apps, which check them (see
|
|
115
|
+
* `SettingsExtension`), and can publish schemas of their own that extend this one.
|
|
116
|
+
*/
|
|
117
|
+
var appSettingsSchema = {
|
|
118
|
+
$schema: SCHEMA_DIALECT,
|
|
119
|
+
$id: schemaUrl("app-settings", APP_SETTINGS_SCHEMA_VERSION),
|
|
120
|
+
"@type": APP_SETTINGS_TYPE,
|
|
106
121
|
type: "object",
|
|
107
|
-
|
|
108
|
-
required: [
|
|
109
|
-
"format",
|
|
110
|
-
"version",
|
|
111
|
-
"settings"
|
|
112
|
-
],
|
|
122
|
+
required: ["$schema", "@type"],
|
|
113
123
|
properties: {
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
maxLength: 100
|
|
118
|
-
},
|
|
119
|
-
version: { const: 1 },
|
|
120
|
-
settings: { $ref: "settings" }
|
|
124
|
+
$schema: fileSchemaUrlSchema,
|
|
125
|
+
"@type": { const: APP_SETTINGS_TYPE },
|
|
126
|
+
...settingsProperties
|
|
121
127
|
}
|
|
122
128
|
};
|
|
123
|
-
export {
|
|
129
|
+
export { APP_SETTINGS_SCHEMA_VERSION, APP_SETTINGS_TYPE, MAX_SAVED_SHORTCUTS, appSettingsSchema, keyComboSchema, settingsSchema };
|
|
@@ -1,18 +1,28 @@
|
|
|
1
1
|
import type { LayerConfig } from "../classes/Layer";
|
|
2
2
|
import type { AppSettings } from "../settings/schema";
|
|
3
|
+
import type { BrushConfig } from "../brushes/types";
|
|
4
|
+
import type { ColourPalette } from "../palette/schema";
|
|
5
|
+
import type { ProfileGraph } from "../profiles";
|
|
6
|
+
import type { DocumentInfo, DrawingDocument } from "../document/schema";
|
|
3
7
|
import { type Rendering } from "../classes/UiSettings";
|
|
4
8
|
/** Version of a saved drawing's shape, so drawings saved by other versions can be recognised */
|
|
5
9
|
export declare const SAVED_DRAWING_VERSION = 1;
|
|
6
10
|
/** Name of the IndexedDB database `IndexedDbLayerStore` keeps drawings in, and `IndexedDbSettingsStore` settings */
|
|
7
11
|
export declare const DATABASE_NAME = "paintcanvas";
|
|
8
|
-
/** Version of the database's object stores (2 added settings) */
|
|
9
|
-
export declare const DATABASE_VERSION =
|
|
12
|
+
/** Version of the database's object stores (2 added settings; 3 added brushes, palettes and profiles) */
|
|
13
|
+
export declare const DATABASE_VERSION = 3;
|
|
14
|
+
/** Kinds of asset kept in the database, each in its own object store, by settings name and asset ID */
|
|
15
|
+
export declare const ASSET_KINDS: readonly ["brushes", "palettes", "profiles"];
|
|
16
|
+
/** A kind of asset kept in the database */
|
|
17
|
+
export type AssetKind = (typeof ASSET_KINDS)[number];
|
|
10
18
|
/** A saved layer's settings (its pixels are kept separately, as a PNG) */
|
|
11
19
|
export type SavedLayer = Required<LayerConfig>;
|
|
12
|
-
/** A saved drawing: its size, its layers (top first) without their pixels, and the selected layer */
|
|
20
|
+
/** A saved drawing: its details, size, its layers (top first) without their pixels, and the selected layer */
|
|
13
21
|
export interface SavedDrawing {
|
|
14
22
|
/** The shape's version (see `SAVED_DRAWING_VERSION`) */
|
|
15
23
|
version: number;
|
|
24
|
+
/** The drawing's details (drawings saved by older versions have none) */
|
|
25
|
+
document?: DocumentInfo;
|
|
16
26
|
width: number;
|
|
17
27
|
height: number;
|
|
18
28
|
layers: SavedLayer[];
|
|
@@ -93,6 +103,75 @@ export declare class IndexedDbSettingsStore implements SettingsStoreLike {
|
|
|
93
103
|
load(): Promise<unknown>;
|
|
94
104
|
save(settings: AppSettings): Promise<void>;
|
|
95
105
|
}
|
|
106
|
+
/** An asset: anything with an ID */
|
|
107
|
+
export interface Asset {
|
|
108
|
+
id: string;
|
|
109
|
+
}
|
|
110
|
+
/** Where assets of one kind (e.g. brush presets) are kept (see `IndexedDbAssetStore`) */
|
|
111
|
+
export interface AssetStoreLike<T extends Asset> {
|
|
112
|
+
/** The saved assets (untrusted: check them before using them), in the order they were first saved */
|
|
113
|
+
list(): Promise<unknown[]>;
|
|
114
|
+
/** Save an asset, replacing one with the same ID */
|
|
115
|
+
put(asset: T): Promise<void>;
|
|
116
|
+
/** Delete an asset */
|
|
117
|
+
remove(id: string): Promise<void>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Keeps assets of one kind (e.g. brush presets) in the browser's IndexedDB database (`DATABASE_NAME`), under a name
|
|
121
|
+
* (like `IndexedDbSettingsStore`'s), each in its own record so saving one doesn't rewrite the others.
|
|
122
|
+
*
|
|
123
|
+
* @example
|
|
124
|
+
* const store = new IndexedDbAssetStore<BrushConfig>("brushes");
|
|
125
|
+
* await store.put(myPreset);
|
|
126
|
+
*/
|
|
127
|
+
export declare class IndexedDbAssetStore<T extends Asset> implements AssetStoreLike<T> {
|
|
128
|
+
readonly kind: AssetKind;
|
|
129
|
+
readonly name: string;
|
|
130
|
+
private readonly connection;
|
|
131
|
+
/**
|
|
132
|
+
* @param kind - the kind of asset
|
|
133
|
+
* @param name - the settings' name the assets belong to (`DEFAULT_SETTINGS_NAME` by default)
|
|
134
|
+
* @param factory - the IndexedDB to use (the browser's by default)
|
|
135
|
+
*/
|
|
136
|
+
constructor(kind: AssetKind, name?: string, factory?: IDBFactory);
|
|
137
|
+
list(): Promise<unknown[]>;
|
|
138
|
+
put(asset: T): Promise<void>;
|
|
139
|
+
remove(id: string): Promise<void>;
|
|
140
|
+
/** The keys of this name's assets: `[name, id]` (arrays sort after strings) */
|
|
141
|
+
private keys;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Where whole documents are kept away from the browser, e.g. a user's account online (see `RemoteDocumentAutosave`).
|
|
145
|
+
* Saving can be slow, so it's done less often than keeping the drawing in the browser.
|
|
146
|
+
*/
|
|
147
|
+
export interface DocumentStoreLike {
|
|
148
|
+
/** Names the store for the user, e.g. "Bluesky" (shown while saving) */
|
|
149
|
+
readonly label?: string;
|
|
150
|
+
/**
|
|
151
|
+
* Save a document, replacing the one with the same ID. Call `onProgress` with how much is done (0 to 1), if known.
|
|
152
|
+
*/
|
|
153
|
+
save(document: DrawingDocument, onProgress?: (done: number) => void): Promise<void>;
|
|
154
|
+
/** A saved document by ID, or undefined if there's none */
|
|
155
|
+
load(id: string): Promise<DrawingDocument | undefined>;
|
|
156
|
+
}
|
|
157
|
+
/** Where the user's assets are kept, by kind. Assets of a kind without a store are kept in memory only. */
|
|
158
|
+
export interface AssetStores {
|
|
159
|
+
brushes?: AssetStoreLike<BrushConfig>;
|
|
160
|
+
palettes?: AssetStoreLike<ColourPalette>;
|
|
161
|
+
profiles?: AssetStoreLike<ProfileGraph>;
|
|
162
|
+
}
|
|
163
|
+
/** Where the user's settings and assets are kept */
|
|
164
|
+
export interface PaintCanvasStores extends AssetStores {
|
|
165
|
+
settings?: SettingsStoreLike;
|
|
166
|
+
}
|
|
167
|
+
/**
|
|
168
|
+
* Stores keeping the user's settings and assets in the browser's IndexedDB database, under a name.
|
|
169
|
+
*
|
|
170
|
+
* @example
|
|
171
|
+
* const { settings, ...assets } = indexedDbStores("my-app");
|
|
172
|
+
* canvas.useAssetStores(assets);
|
|
173
|
+
*/
|
|
174
|
+
export declare const indexedDbStores: (name?: string, factory?: IDBFactory) => Required<PaintCanvasStores>;
|
|
96
175
|
/**
|
|
97
176
|
* The browser storage key that keeps the rendering chosen with the app settings of a name (see
|
|
98
177
|
* `loadRenderingChoice`).
|
|
@@ -4,19 +4,26 @@ import { isRendering } from "../classes/UiSettings/index.js";
|
|
|
4
4
|
var SAVED_DRAWING_VERSION = 1;
|
|
5
5
|
/** Name of the IndexedDB database `IndexedDbLayerStore` keeps drawings in, and `IndexedDbSettingsStore` settings */
|
|
6
6
|
var DATABASE_NAME = "paintcanvas";
|
|
7
|
-
/** Version of the database's object stores (2 added settings) */
|
|
8
|
-
var DATABASE_VERSION =
|
|
7
|
+
/** Version of the database's object stores (2 added settings; 3 added brushes, palettes and profiles) */
|
|
8
|
+
var DATABASE_VERSION = 3;
|
|
9
9
|
/** Object store of saved drawings, by name */
|
|
10
10
|
var DRAWINGS = "drawings";
|
|
11
11
|
/** Object store of layer images (PNG blobs), by drawing name and layer ID */
|
|
12
12
|
var IMAGES = "images";
|
|
13
13
|
/** Object store of app settings, by name */
|
|
14
14
|
var SETTINGS = "settings";
|
|
15
|
+
/** Kinds of asset kept in the database, each in its own object store, by settings name and asset ID */
|
|
16
|
+
var ASSET_KINDS = [
|
|
17
|
+
"brushes",
|
|
18
|
+
"palettes",
|
|
19
|
+
"profiles"
|
|
20
|
+
];
|
|
15
21
|
/** Every object store, created when the database is first opened or upgraded */
|
|
16
22
|
var OBJECT_STORES = [
|
|
17
23
|
DRAWINGS,
|
|
18
24
|
IMAGES,
|
|
19
|
-
SETTINGS
|
|
25
|
+
SETTINGS,
|
|
26
|
+
...ASSET_KINDS
|
|
20
27
|
];
|
|
21
28
|
/**
|
|
22
29
|
* Wait for an IndexedDB request's result.
|
|
@@ -37,7 +44,7 @@ var completed = (transaction) => new Promise((resolve, reject) => {
|
|
|
37
44
|
* database, this connection closes and `onClose` is called, so the next use opens it again.
|
|
38
45
|
*/
|
|
39
46
|
var openDatabase = (factory, onClose) => new Promise((resolve, reject) => {
|
|
40
|
-
const request = factory.open(DATABASE_NAME,
|
|
47
|
+
const request = factory.open(DATABASE_NAME, 3);
|
|
41
48
|
request.onupgradeneeded = () => {
|
|
42
49
|
const database = request.result;
|
|
43
50
|
for (const store of OBJECT_STORES) if (!database.objectStoreNames.contains(store)) database.createObjectStore(store);
|
|
@@ -170,6 +177,76 @@ var IndexedDbSettingsStore = class {
|
|
|
170
177
|
await done;
|
|
171
178
|
}
|
|
172
179
|
};
|
|
180
|
+
/** The order of the asset last saved for the first time */
|
|
181
|
+
var lastOrder = 0;
|
|
182
|
+
/**
|
|
183
|
+
* The order of an asset saved for the first time: when it was saved, and always after the one before.
|
|
184
|
+
*/
|
|
185
|
+
var nextOrder = () => lastOrder = Math.max(Date.now(), lastOrder + 1);
|
|
186
|
+
/**
|
|
187
|
+
* Keeps assets of one kind (e.g. brush presets) in the browser's IndexedDB database (`DATABASE_NAME`), under a name
|
|
188
|
+
* (like `IndexedDbSettingsStore`'s), each in its own record so saving one doesn't rewrite the others.
|
|
189
|
+
*
|
|
190
|
+
* @example
|
|
191
|
+
* const store = new IndexedDbAssetStore<BrushConfig>("brushes");
|
|
192
|
+
* await store.put(myPreset);
|
|
193
|
+
*/
|
|
194
|
+
var IndexedDbAssetStore = class {
|
|
195
|
+
kind;
|
|
196
|
+
name;
|
|
197
|
+
connection;
|
|
198
|
+
/**
|
|
199
|
+
* @param kind - the kind of asset
|
|
200
|
+
* @param name - the settings' name the assets belong to (`DEFAULT_SETTINGS_NAME` by default)
|
|
201
|
+
* @param factory - the IndexedDB to use (the browser's by default)
|
|
202
|
+
*/
|
|
203
|
+
constructor(kind, name = DEFAULT_SETTINGS_NAME, factory = indexedDB) {
|
|
204
|
+
this.kind = kind;
|
|
205
|
+
this.name = name;
|
|
206
|
+
this.connection = new DatabaseConnection(factory);
|
|
207
|
+
}
|
|
208
|
+
async list() {
|
|
209
|
+
return (await result((await this.connection.open()).transaction(this.kind, "readonly").objectStore(this.kind).getAll(this.keys()))).sort((a, b) => a.order - b.order).map((record) => record.asset);
|
|
210
|
+
}
|
|
211
|
+
async put(asset) {
|
|
212
|
+
const transaction = (await this.connection.open()).transaction(this.kind, "readwrite");
|
|
213
|
+
const done = completed(transaction);
|
|
214
|
+
const store = transaction.objectStore(this.kind);
|
|
215
|
+
const key = [this.name, asset.id];
|
|
216
|
+
const existing = store.get(key);
|
|
217
|
+
existing.onsuccess = () => {
|
|
218
|
+
const order = existing.result?.order ?? nextOrder();
|
|
219
|
+
store.put({
|
|
220
|
+
asset,
|
|
221
|
+
order
|
|
222
|
+
}, key);
|
|
223
|
+
};
|
|
224
|
+
await done;
|
|
225
|
+
}
|
|
226
|
+
async remove(id) {
|
|
227
|
+
const transaction = (await this.connection.open()).transaction(this.kind, "readwrite");
|
|
228
|
+
const done = completed(transaction);
|
|
229
|
+
transaction.objectStore(this.kind).delete([this.name, id]);
|
|
230
|
+
await done;
|
|
231
|
+
}
|
|
232
|
+
/** The keys of this name's assets: `[name, id]` (arrays sort after strings) */
|
|
233
|
+
keys() {
|
|
234
|
+
return IDBKeyRange.bound([this.name], [this.name, []]);
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
/**
|
|
238
|
+
* Stores keeping the user's settings and assets in the browser's IndexedDB database, under a name.
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* const { settings, ...assets } = indexedDbStores("my-app");
|
|
242
|
+
* canvas.useAssetStores(assets);
|
|
243
|
+
*/
|
|
244
|
+
var indexedDbStores = (name = DEFAULT_SETTINGS_NAME, factory = indexedDB) => ({
|
|
245
|
+
settings: new IndexedDbSettingsStore(name, factory),
|
|
246
|
+
brushes: new IndexedDbAssetStore("brushes", name, factory),
|
|
247
|
+
palettes: new IndexedDbAssetStore("palettes", name, factory),
|
|
248
|
+
profiles: new IndexedDbAssetStore("profiles", name, factory)
|
|
249
|
+
});
|
|
173
250
|
/**
|
|
174
251
|
* The browser storage key that keeps the rendering chosen with the app settings of a name (see
|
|
175
252
|
* `loadRenderingChoice`).
|
|
@@ -206,4 +283,4 @@ var saveRenderingChoice = (name, rendering, storage = globalThis.localStorage) =
|
|
|
206
283
|
storage?.setItem(renderingChoiceKey(name), rendering);
|
|
207
284
|
} catch {}
|
|
208
285
|
};
|
|
209
|
-
export { DATABASE_NAME, DATABASE_VERSION, DEFAULT_SETTINGS_NAME, IndexedDbSettingsStore, SAVED_DRAWING_VERSION, IndexedDbLayerStore as default, loadRenderingChoice, renderingChoiceKey, saveRenderingChoice };
|
|
286
|
+
export { ASSET_KINDS, DATABASE_NAME, DATABASE_VERSION, DEFAULT_SETTINGS_NAME, IndexedDbAssetStore, IndexedDbSettingsStore, SAVED_DRAWING_VERSION, IndexedDbLayerStore as default, indexedDbStores, loadRenderingChoice, renderingChoiceKey, saveRenderingChoice };
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
// Types for the generated validators (see validators.generated.js).
|
|
2
|
-
import type {
|
|
3
|
-
import type {
|
|
4
|
-
import type {
|
|
5
|
-
import type {
|
|
2
|
+
import type { AssetCollectionFile } from "../assets/schema";
|
|
3
|
+
import type { BrushConfig } from "../brushes/types";
|
|
4
|
+
import type { ProfileGraph } from "../profiles";
|
|
5
|
+
import type { DocumentFile } from "../document/schema";
|
|
6
|
+
import type { ColourPalette } from "../palette/schema";
|
|
7
|
+
import type { AppSettings, AppSettingsFile } from "../settings/schema";
|
|
6
8
|
import type {
|
|
7
9
|
HistoryMessage,
|
|
8
10
|
PatchMessage,
|
|
@@ -22,11 +24,20 @@ export interface Validator<T> {
|
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export declare const validateBrushPreset: Validator<Record<string, unknown>>;
|
|
25
|
-
export declare const
|
|
27
|
+
export declare const validateBrushPresetCollection: Validator<
|
|
28
|
+
AssetCollectionFile<BrushConfig>
|
|
29
|
+
>;
|
|
30
|
+
export declare const validateColourPalette: Validator<ColourPalette>;
|
|
31
|
+
export declare const validateColourPaletteCollection: Validator<
|
|
32
|
+
AssetCollectionFile<ColourPalette>
|
|
33
|
+
>;
|
|
34
|
+
export declare const validateProfileGraph: Validator<ProfileGraph>;
|
|
35
|
+
export declare const validateProfileGraphCollection: Validator<
|
|
36
|
+
AssetCollectionFile<ProfileGraph>
|
|
37
|
+
>;
|
|
26
38
|
export declare const validatePatchMessage: Validator<PatchMessage>;
|
|
27
39
|
export declare const validateStrokeMessage: Validator<StrokeMessage>;
|
|
28
40
|
export declare const validateHistoryMessage: Validator<HistoryMessage>;
|
|
29
|
-
export declare const validateDocument: Validator<
|
|
30
|
-
export declare const validatePaletteFile: Validator<PaletteFile>;
|
|
41
|
+
export declare const validateDocument: Validator<DocumentFile>;
|
|
31
42
|
export declare const validateSettings: Validator<AppSettings>;
|
|
32
|
-
export declare const
|
|
43
|
+
export declare const validateAppSettings: Validator<AppSettingsFile>;
|