Skip to content

Commit b84216d

Browse files
committed
async useDomState
1 parent 4443c63 commit b84216d

File tree

7 files changed

+40
-56
lines changed

7 files changed

+40
-56
lines changed

addons/html_builder/static/src/builder.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,10 @@ export class Builder extends Component {
9292
this.state.canRedo = this.editor.shared.history.canRedo();
9393
this.updateInvisibleEls();
9494
editorBus.trigger("UPDATE_EDITING_ELEMENT");
95-
editorBus.trigger("DOM_UPDATED");
95+
const getStatePromises = [];
96+
const { promise: updatePromise, resolve } = Promise.withResolvers();
97+
editorBus.trigger("DOM_UPDATED", { getStatePromises, updatePromise });
98+
Promise.all(getStatePromises).then(resolve);
9699
}
97100
},
98101
reloadEditor: (param = {}) => {

addons/html_builder/static/src/core/utils.js

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { isElement, isTextNode } from "@html_editor/utils/dom_info";
2+
import { on } from "@odoo/hoot-dom";
23
import {
34
Component,
45
onMounted,
@@ -25,21 +26,18 @@ function isConnectedElement(el) {
2526
export function useDomState(getState, { checkEditingElement = true, onReady } = {}) {
2627
const env = useEnv();
2728
const isValid = (el) => (!el && !checkEditingElement) || isConnectedElement(el);
28-
const handler = () => {
29+
const handler = async (ev) => {
2930
const editingElement = env.getEditingElement();
3031
if (isValid(editingElement)) {
31-
Object.assign(state, getState(editingElement));
32+
const newStatePromise = getState(editingElement);
33+
ev?.detail.getStatePromises.push(newStatePromise);
34+
const newState = await newStatePromise;
35+
await ev?.detail.updatePromise;
36+
Object.assign(state, newState);
3237
}
3338
};
3439
const state = useState({});
35-
if (onReady) {
36-
onReady.then(() => {
37-
handler();
38-
});
39-
} else {
40-
handler();
41-
}
42-
40+
onWillStart(() => (onReady ? onReady.then(() => handler()) : handler()));
4341
useBus(env.editorBus, "DOM_UPDATED", handler);
4442
return state;
4543
}

addons/html_builder/static/src/plugins/image/image_filter_option.js

Lines changed: 6 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
22
import { shouldPreventGifTransformation } from "@html_editor/main/media/image_post_process_plugin";
33
import { loadImageInfo } from "@html_editor/utils/image_processing";
4-
import { KeepLast } from "@web/core/utils/concurrency";
54

65
export class ImageFilterOption extends BaseOptionComponent {
76
static template = "html_builder.ImageFilterOption";
@@ -13,22 +12,14 @@ export class ImageFilterOption extends BaseOptionComponent {
1312
};
1413
setup() {
1514
super.setup();
16-
const keepLast = new KeepLast();
17-
this.state = useDomState((editingElement) => {
18-
keepLast
19-
.add(
20-
loadImageInfo(editingElement).then((data) => ({
21-
...editingElement.dataset,
22-
...data,
23-
}))
24-
)
25-
.then((data) => {
26-
this.state.showFilter =
27-
data.mimetypeBeforeConversion && !shouldPreventGifTransformation(data);
28-
});
15+
this.state = useDomState(async (editingElement) => {
16+
const data = await loadImageInfo(editingElement).then((data) => ({
17+
...editingElement.dataset,
18+
...data,
19+
}));
2920
return {
3021
isCustomFilter: editingElement.dataset.glFilter === "custom",
31-
showFilter: false,
22+
showFilter: data.mimetypeBeforeConversion && !shouldPreventGifTransformation(data),
3223
};
3324
});
3425
}

addons/html_builder/static/src/plugins/image/image_format_option.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
2-
import { KeepLast } from "@web/core/utils/concurrency";
32
import { getImageSrc, getMimetype } from "@html_editor/utils/image";
43
import { clamp } from "@web/core/utils/numbers";
54

@@ -15,22 +14,15 @@ export class ImageFormatOption extends BaseOptionComponent {
1514
MAX_SUGGESTED_WIDTH = 1920;
1615
setup() {
1716
super.setup();
18-
const keepLast = new KeepLast();
19-
this.state = useDomState((editingElement) => {
20-
keepLast
21-
.add(
22-
this.env.editor.shared.imageFormatOption.computeAvailableFormats(
23-
editingElement,
24-
this.computeMaxDisplayWidth.bind(this)
25-
)
26-
)
27-
.then((formats) => {
28-
const hasSrc = !!getImageSrc(editingElement);
29-
this.state.formats = hasSrc ? formats : [];
30-
});
17+
this.state = useDomState(async (editingElement) => {
18+
const formats = await this.env.editor.shared.imageFormatOption.computeAvailableFormats(
19+
editingElement,
20+
this.computeMaxDisplayWidth.bind(this)
21+
);
22+
const hasSrc = !!getImageSrc(editingElement);
3123
return {
3224
showQuality: ["image/jpeg", "image/webp"].includes(getMimetype(editingElement)),
33-
formats: [],
25+
formats: hasSrc ? formats : [],
3426
};
3527
});
3628
}

addons/html_builder/static/src/plugins/image/image_tool_option_plugin.js

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { cropperDataFieldsWithAspectRatio, isGif } from "@html_editor/utils/image_processing";
1+
import {
2+
cropperDataFieldsWithAspectRatio,
3+
isGif,
4+
loadImageInfo,
5+
} from "@html_editor/utils/image_processing";
26
import { registry } from "@web/core/registry";
37
import { Plugin } from "@html_editor/plugin";
48
import { ImageToolOption } from "./image_tool_option";
@@ -192,11 +196,12 @@ class ImageToolOptionPlugin extends Plugin {
192196
};
193197
}
194198
async canHaveHoverEffect(img) {
199+
const getDataset = async () => Object.assign({}, img.dataset, await loadImageInfo(img));
195200
return (
196201
img.tagName === "IMG" &&
197202
!this.isDeviceShape(img) &&
198203
!this.isAnimatedShape(img) &&
199-
this.isImageSupportedForShapes(img) &&
204+
this.isImageSupportedForShapes(img, await getDataset()) &&
200205
!(await isImageCorsProtected(img))
201206
);
202207
}
@@ -212,8 +217,8 @@ class ImageToolOptionPlugin extends Plugin {
212217
// todo: to implement while implementing the animated shapes
213218
return false;
214219
}
215-
isImageSupportedForShapes(img) {
216-
return img.dataset.originalId && isImageSupportedForProcessing(getMimetype(img));
220+
isImageSupportedForShapes(img, dataset = img.dataset) {
221+
return dataset.originalId && isImageSupportedForProcessing(getMimetype(img));
217222
}
218223
}
219224
registry.category("website-plugins").add(ImageToolOptionPlugin.id, ImageToolOptionPlugin);

addons/html_builder/static/src/website_builder/plugins/options/animate_option.js

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { KeepLast } from "@web/core/utils/concurrency";
21
import { BaseOptionComponent, useDomState } from "@html_builder/core/utils";
32
import { isImageSupportedForStyle } from "@html_builder/plugins/image/replace_media_option";
43

@@ -12,19 +11,15 @@ export class AnimateOption extends BaseOptionComponent {
1211

1312
setup() {
1413
super.setup();
15-
const keeplast = new KeepLast();
16-
this.state = useDomState((editingElement) => {
14+
this.state = useDomState(async (editingElement) => {
1715
const hasAnimateClass = editingElement.classList.contains("o_animate");
1816

19-
// todo: maybe add a spinner
20-
keeplast.add(this.props.canHaveHoverEffect(editingElement)).then((result) => {
21-
this.state.canHover = result;
22-
});
17+
const canHover = await this.props.canHaveHoverEffect(editingElement);
2318

2419
return {
2520
isOptionActive: this.isOptionActive(editingElement),
2621
hasAnimateClass: hasAnimateClass,
27-
canHover: false,
22+
canHover,
2823
isLimitedEffect: this.limitedEffects.some((className) =>
2924
editingElement.classList.contains(className)
3025
),

addons/html_editor/static/src/utils/image.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ export function backgroundImagePartsToCss(parts) {
3535
* @param {HTMLImageElement} image
3636
* @returns {string|null} The mimetype of the image.
3737
*/
38-
export function getMimetype(image) {
38+
export function getMimetype(image, dataset = image.dataset) {
3939
const src = getImageSrc(image);
4040

4141
return (
42-
image.dataset.mimetype ||
43-
image.dataset.mimetypeBeforeConversion ||
42+
dataset.mimetype ||
43+
dataset.mimetypeBeforeConversion ||
4444
(src &&
4545
((src.endsWith(".png") && "image/png") ||
4646
(src.endsWith(".webp") && "image/webp") ||

0 commit comments

Comments
 (0)