diff --git a/addons/website/__manifest__.py b/addons/website/__manifest__.py index a44a94a31aa..4d62e453d21 100644 --- a/addons/website/__manifest__.py +++ b/addons/website/__manifest__.py @@ -125,7 +125,6 @@ 'website/static/src/js/utils.js', 'website/static/src/js/content/website_root.js', 'website/static/src/js/widgets/dialog.js', - 'website/static/src/components/fullscreen_indication/fullscreen_indication.js', 'website/static/src/js/content/compatibility.js', 'website/static/src/js/content/menu.js', 'website/static/src/js/content/snippets.animation.js', @@ -179,6 +178,8 @@ 'website/static/src/components/dialog/dialog.scss', 'website/static/src/components/switch/switch.js', 'website/static/src/components/switch/switch.scss', + 'website/static/src/components/fullscreen_indication/fullscreen_indication.js', + 'website/static/src/components/fullscreen_indication/fullscreen_indication.scss', 'website/static/src/systray_items/*.js', 'website/static/src/systray_items/*.scss', ], diff --git a/addons/website/static/src/client_actions/website_preview/website_preview.js b/addons/website/static/src/client_actions/website_preview/website_preview.js index 4081a9be3f2..802d47ae96c 100644 --- a/addons/website/static/src/client_actions/website_preview/website_preview.js +++ b/addons/website/static/src/client_actions/website_preview/website_preview.js @@ -116,6 +116,12 @@ export class WebsitePreview extends Component { window.location.replace(href); } }); + this.iframe.el.contentDocument.addEventListener('keydown', ev => { + this.iframe.el.dispatchEvent(new KeyboardEvent('keydown', ev)); + }); + this.iframe.el.contentDocument.addEventListener('keyup', ev => { + this.iframe.el.dispatchEvent(new KeyboardEvent('keyup', ev)); + }); } } WebsitePreview.template = 'website.WebsitePreview'; diff --git a/addons/website/static/src/client_actions/website_preview/website_preview.scss b/addons/website/static/src/client_actions/website_preview/website_preview.scss index 89b84d2f969..3ed836b4881 100644 --- a/addons/website/static/src/client_actions/website_preview/website_preview.scss +++ b/addons/website/static/src/client_actions/website_preview/website_preview.scss @@ -9,3 +9,19 @@ border: none; } } + +.o_website_fullscreen, .editor_has_snippets { + header { + .o_main_navbar { + height: 0px; + transform: translateY(-$o-navbar-height); + border-bottom: 0px; + } + } +} + +header { + .o_main_navbar { + transition: transform 400ms ease, height 400ms ease, border-bottom 400ms ease; + } +} diff --git a/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js index 44ffc379994..f7ef058d72e 100644 --- a/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js +++ b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.js @@ -1,40 +1,27 @@ /** @odoo-module **/ -import Widget from 'web.Widget'; +const { Component, xml, useState } = owl; -export const FullscreenIndication = Widget.extend({ - xmlDependencies: ['/website/static/src/xml/website.xml'], - template: 'website.fullscreen_indication', +export class FullscreenIndication extends Component { + setup() { + this.state = useState({ isVisible: false }); + this.props.bus.on('FULLSCREEN-INDICATION-SHOW', this, this.show); + this.props.bus.on('FULLSCREEN-INDICATION-HIDE', this, this.hide); + } - init: function () { - this.visible = false; - this.displayTime = 2000; - this._super(...arguments); - }, + show() { + setTimeout(() => this.state.isVisible = true); + this.autofade = setTimeout(() => this.state.isVisible = false, 2000); + } - //-------------------------------------------------------------------------- - // Public - //-------------------------------------------------------------------------- - - /** - * Displays the fullscreen indication modal - */ - show: function () { - clearTimeout(this.autofade); - this.visible = true; - this.el.classList.add('o_transition', 'o_visible'); - this.autofade = setTimeout(() => { - this.hide(true); - }, this.displayTime); - }, - /** - * Hides the fullscreen indication modal with optionnal transition - * - * @param {boolean} [withTransition=false] - */ - hide: function (withTransition = false) { - this.el.classList.toggle('o_transition', withTransition); - this.el.classList.remove('o_visible'); - this.visible = false; - }, -}); + hide() { + if (this.state.isVisible) { + this.state.isVisible = false; + clearTimeout(this.autofade); + } + } +} +FullscreenIndication.template = xml` +
+

Press esc to exit full screen

+
`; diff --git a/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.scss b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.scss new file mode 100644 index 00000000000..9f4222bcef1 --- /dev/null +++ b/addons/website/static/src/components/fullscreen_indication/fullscreen_indication.scss @@ -0,0 +1,29 @@ +.o_fullscreen_indication { + display: flex; + position: absolute; + width: 100%; + align-items: center; + justify-content: center; + top: 0; + margin-top: $o-navbar-height!important; + opacity: 0; + pointer-events: none; + transition: opacity 400ms ease; + + p { + padding: 15px 30px; + background-color: rgba(0, 0, 0, 0.7); + color: white; + span { + border: 1px solid white; + border-color: white; + border-radius: 5px; + padding: 7px 5px; + margin: 5px; + } + } + + &.o_visible { + opacity: 1; + } +} diff --git a/addons/website/static/src/js/content/redirect.js b/addons/website/static/src/js/content/redirect.js index 482d93db7e0..fc42161742f 100644 --- a/addons/website/static/src/js/content/redirect.js +++ b/addons/website/static/src/js/content/redirect.js @@ -7,6 +7,8 @@ const _t = str => str; /** * This script, served with frontend pages, displays buttons in the top left * corner to provide the authenticated user an access to his odoo backend. + * In the case of the page being viewed in the website_preview client action, + * it will forward some events to its parent. */ document.addEventListener('DOMContentLoaded', () => { if (session.is_website_user) { diff --git a/addons/website/static/src/js/content/website_root.js b/addons/website/static/src/js/content/website_root.js index 4d51544d21f..9453913ab85 100644 --- a/addons/website/static/src/js/content/website_root.js +++ b/addons/website/static/src/js/content/website_root.js @@ -7,7 +7,6 @@ import {Markup} from 'web.utils'; import session from 'web.session'; import publicRootData from 'web.public.root'; import "web.zoomodoo"; -import { FullscreenIndication } from '@website/components/fullscreen_indication/fullscreen_indication'; export const WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMixin, { // TODO remove KeyboardNavigationMixin in master @@ -35,16 +34,6 @@ export const WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMi }); return this._super(...arguments); }, - /** - * @override - */ - willStart: async function () { - this.fullscreenIndication = new FullscreenIndication(this); - return Promise.all([ - this._super(...arguments), - this.fullscreenIndication.appendTo(document.body), - ]); - }, /** * @override */ @@ -170,45 +159,6 @@ export const WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMi } return this._gmapAPILoading; }, - /** - * Toggles the fullscreen mode. - * - * @private - * @param {boolean} state toggle fullscreen on/off (true/false) - */ - _toggleFullscreen(state) { - this.isFullscreen = state; - if (this.isFullscreen) { - this.fullscreenIndication.show(); - } else { - this.fullscreenIndication.hide(); - } - document.body.classList.add('o_fullscreen_transition'); - document.body.classList.toggle('o_fullscreen', this.isFullscreen); - document.body.style.overflowX = 'hidden'; - let resizing = true; - window.requestAnimationFrame(function resizeFunction() { - window.dispatchEvent(new Event('resize')); - if (resizing) { - window.requestAnimationFrame(resizeFunction); - } - }); - let stopResizing; - const onTransitionEnd = ev => { - if (ev.target === document.body && ev.propertyName === 'padding-top') { - stopResizing(); - } - }; - stopResizing = () => { - resizing = false; - document.body.style.overflowX = ''; - document.body.removeEventListener('transitionend', onTransitionEnd); - document.body.classList.remove('o_fullscreen_transition'); - }; - document.body.addEventListener('transitionend', onTransitionEnd); - // Safeguard in case the transitionend event doesn't trigger for whatever reason. - window.setTimeout(() => stopResizing(), 500); - }, //-------------------------------------------------------------------------- // Handlers @@ -329,7 +279,6 @@ export const WebsiteRoot = publicRootData.PublicRoot.extend(KeyboardNavigationMi if (ev.keyCode !== $.ui.keyCode.ESCAPE || !document.body.contains(ev.target) || ev.target.closest('.modal')) { return KeyboardNavigationMixin._onKeyDown.apply(this, arguments); } - this._toggleFullscreen(!this.isFullscreen); }, }); diff --git a/addons/website/static/src/services/website_service.js b/addons/website/static/src/services/website_service.js index be467016f5a..0f8e1a81ad2 100644 --- a/addons/website/static/src/services/website_service.js +++ b/addons/website/static/src/services/website_service.js @@ -2,7 +2,9 @@ import { registry } from '@web/core/registry'; -const { reactive } = owl; +import { FullscreenIndication } from '../components/fullscreen_indication/fullscreen_indication'; + +const { reactive, EventBus } = owl; const websiteSystrayRegistry = registry.category('website_systray'); @@ -18,19 +20,33 @@ export const unslugHtmlDataObject = (repr) => { }; export const websiteService = { - dependencies: ['orm', 'action'], - async start(env, { orm, action }) { + dependencies: ['orm', 'action', 'hotkey'], + async start(env, { orm, action, hotkey }) { let websites = []; let currentWebsiteId; let currentMetadata = {}; + let fullscreen; const context = reactive({ showNewContentModal: false, }); + const bus = new EventBus(); const setCurrentWebsiteId = id => { currentWebsiteId = id; websiteSystrayRegistry.trigger('EDIT-WEBSITE'); }; + hotkey.add("escape", () => { + // Toggle fullscreen mode when pressing escape. + if (currentWebsiteId) { + fullscreen = !fullscreen; + document.body.classList.toggle('o_website_fullscreen', fullscreen); + bus.trigger((fullscreen ? 'FULLSCREEN-INDICATION-SHOW' : 'FULLSCREEN-INDICATION-HIDE')); + } + }); + registry.category('main_components').add('FullscreenIndication', { + Component: FullscreenIndication, + props: { bus }, + }); return { set currentWebsiteId(id) { setCurrentWebsiteId(id);