[ADD] web_editor: full screen image preview on dblclick (html field)
When double-clicking on an image in an html field, display it "full screen" (similar to clicking on an image in the attachments list). This replaces the current behavior (which is to open the media selector to replace the current image - the Replace action remains available in the toolbar). In the toolbar for images, display an icon that users can click on to open the full screen preview as well. task-3109331 closes odoo/odoo#119625 Related: odoo/enterprise#40450 Signed-off-by: David Monjoie (dmo) <dmo@odoo.com>
This commit is contained in:
@@ -235,6 +235,7 @@ export class HtmlField extends Component {
|
||||
value: this.props.record.data[this.props.name],
|
||||
autostart: false,
|
||||
onAttachmentChange: this._onAttachmentChange.bind(this),
|
||||
onDblClickEditableMedia: this._onDblClickEditableMedia.bind(this),
|
||||
onWysiwygBlur: this._onWysiwygBlur.bind(this),
|
||||
...wysiwygOptions,
|
||||
...dynamicPlaceholderOptions,
|
||||
@@ -570,6 +571,12 @@ export class HtmlField extends Component {
|
||||
},
|
||||
});
|
||||
}
|
||||
_onDblClickEditableMedia(ev) {
|
||||
const el = ev.target;
|
||||
if (el.nodeName === 'IMG' && el.src) {
|
||||
this.wysiwyg.showImageFullscreen(el.src);
|
||||
}
|
||||
}
|
||||
_onWysiwygBlur() {
|
||||
this.commitChanges();
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import { PeerToPeer } from "@web_editor/js/wysiwyg/PeerToPeer";
|
||||
import { uniqueId } from "@web/core/utils/functions";
|
||||
import { groupBy } from "@web/core/utils/arrays";
|
||||
import { debounce } from "@web/core/utils/timing";
|
||||
import { registry } from "@web/core/registry";
|
||||
import { FileViewer } from "@web/core/file_viewer/file_viewer";
|
||||
|
||||
var _t = core._t;
|
||||
const QWeb = core.qweb;
|
||||
@@ -68,6 +70,8 @@ const PTP_CLIENT_DISCONNECTED_STATES = [
|
||||
// this is a local cache for ice server descriptions
|
||||
let ICE_SERVERS = null;
|
||||
|
||||
let fileViewerId = 0;
|
||||
|
||||
const Wysiwyg = Widget.extend({
|
||||
defaultOptions: {
|
||||
lang: 'odoo',
|
||||
@@ -306,29 +310,17 @@ const Wysiwyg = Widget.extend({
|
||||
|
||||
this.$editable.on('click', '.o_image, .media_iframe_video', e => e.preventDefault());
|
||||
this.showTooltip = true;
|
||||
this.$editable.on('dblclick', mediaSelector, function () {
|
||||
if (this.isContentEditable || (this.parentElement && this.parentElement.isContentEditable)) {
|
||||
self.showTooltip = false;
|
||||
this.$editable.on('dblclick', mediaSelector, ev => {
|
||||
const target = ev.target;
|
||||
if (target.isContentEditable || (target.parentElement && target.parentElement.isContentEditable)) {
|
||||
this.showTooltip = false;
|
||||
|
||||
const selection = self.odooEditor.document.getSelection();
|
||||
const anchorNode = selection.anchorNode;
|
||||
if (isProtected(anchorNode)) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $el = $(this);
|
||||
let params = {node: this};
|
||||
$el.selectElement();
|
||||
|
||||
if (!$el.parent().hasClass('o_stars')) {
|
||||
// Waiting for all the options to be initialized before
|
||||
// opening the media dialog and only if the media has not
|
||||
// been deleted in the meantime.
|
||||
self.waitForEmptyMutexAction().then(() => {
|
||||
if ($el[0].parentElement) {
|
||||
self.openMediaDialog(params);
|
||||
}
|
||||
});
|
||||
if (!isProtected(this.odooEditor.document.getSelection().anchorNode)) {
|
||||
if (this.options.onDblClickEditableMedia && target.nodeName === 'IMG' && target.src) {
|
||||
this.options.onDblClickEditableMedia(ev);
|
||||
} else {
|
||||
this._onDblClickEditableMedia(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -1365,6 +1357,33 @@ const Wysiwyg = Widget.extend({
|
||||
this.linkTools = undefined;
|
||||
}
|
||||
},
|
||||
/**
|
||||
* Take an image's URL and display it in a fullscreen viewer.
|
||||
*
|
||||
* @todo should use `useFileViewer` instead once Wysiwyg becomes an Owl Component.
|
||||
* @param {string} url
|
||||
*/
|
||||
showImageFullscreen(url) {
|
||||
const viewerId = `web.file_viewer${fileViewerId++}`;
|
||||
registry.category("main_components").add(viewerId, {
|
||||
Component: FileViewer,
|
||||
props: {
|
||||
files: [{
|
||||
isImage: true,
|
||||
isViewable: true,
|
||||
displayName: url,
|
||||
defaultSource: url,
|
||||
downloadUrl: url,
|
||||
}],
|
||||
startIndex: 0,
|
||||
close: () => {
|
||||
registry.category('main_components').remove(viewerId);
|
||||
},
|
||||
},
|
||||
});
|
||||
this.odooEditor.document.getSelection()?.removeAllRanges();
|
||||
this.odooEditor.editable.blur();
|
||||
},
|
||||
/**
|
||||
* Open the media dialog.
|
||||
*
|
||||
@@ -1535,6 +1554,12 @@ const Wysiwyg = Widget.extend({
|
||||
if (!options.snippets) {
|
||||
$toolbar.find('#justify, #media-insert').remove();
|
||||
}
|
||||
$toolbar.find('#image-fullscreen').click(() => {
|
||||
if (!this.lastMediaClicked?.src) {
|
||||
return;
|
||||
}
|
||||
this.showImageFullscreen(this.lastMediaClicked.src);
|
||||
})
|
||||
$toolbar.find('#media-insert, #media-replace, #media-description').click(openTools);
|
||||
$toolbar.find('#create-link').click(openTools);
|
||||
$toolbar.find('#image-shape div, #fa-spin').click(e => {
|
||||
@@ -1877,6 +1902,7 @@ const Wysiwyg = Widget.extend({
|
||||
const isInMedia = $target.is(mediaSelector) && !$target.parent().hasClass('o_stars') && e.target &&
|
||||
(e.target.isContentEditable || (e.target.parentElement && e.target.parentElement.isContentEditable));
|
||||
this.toolbar.$el.find([
|
||||
'#image-preview',
|
||||
'#image-shape',
|
||||
'#image-width',
|
||||
'#image-padding',
|
||||
@@ -2471,6 +2497,20 @@ const Wysiwyg = Widget.extend({
|
||||
this.options.onAttachmentChange(attachment);
|
||||
}
|
||||
},
|
||||
_onDblClickEditableMedia(ev) {
|
||||
const $el = $(ev.target);
|
||||
$el.selectElement();
|
||||
if (!$el.parent().hasClass('o_stars')) {
|
||||
// Waiting for all the options to be initialized before
|
||||
// opening the media dialog and only if the media has not
|
||||
// been deleted in the meantime.
|
||||
this.waitForEmptyMutexAction().then(() => {
|
||||
if ($el[0].parentElement) {
|
||||
this.openMediaDialog({ node: ev.target });
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_onSelectionChange() {
|
||||
if (this.odooEditor.autohideToolbar) {
|
||||
const isVisible = this.linkPopover && this.linkPopover.el.offsetParent;
|
||||
|
||||
@@ -146,6 +146,10 @@
|
||||
</div>
|
||||
</t>
|
||||
|
||||
<div id="image-preview" class="btn-group">
|
||||
<div id="image-fullscreen" title="Full screen" class="fa fa-search-plus btn editor-ignore"></div>
|
||||
</div>
|
||||
|
||||
<div id="link" class="btn-group">
|
||||
<div id="media-insert" title="Insert media" class="fa fa-file-image-o fa-fw btn editor-ignore"></div>
|
||||
<div id="create-link" title="Insert or edit link" class="fa fa-link fa-fw btn editor-ignore"></div>
|
||||
|
||||
Reference in New Issue
Block a user