@@ -4,19 +4,22 @@ import {
4
4
onMounted ,
5
5
onWillDestroy ,
6
6
onWillStart ,
7
+ useEffect ,
7
8
useRef ,
8
9
useState ,
9
10
useSubEnv ,
10
11
} from "@odoo/owl" ;
11
12
import { LazyComponent , loadBundle } from "@web/core/assets" ;
12
13
import { browser } from "@web/core/browser/browser" ;
14
+ import { getActiveHotkey } from "@web/core/hotkeys/hotkey_service" ;
13
15
import { _t } from "@web/core/l10n/translation" ;
14
16
import { registry } from "@web/core/registry" ;
15
17
import { ResizablePanel } from "@web/core/resizable_panel/resizable_panel" ;
16
18
import { Deferred } from "@web/core/utils/concurrency" ;
17
19
import { uniqueId } from "@web/core/utils/functions" ;
18
20
import { useChildRef , useService } from "@web/core/utils/hooks" ;
19
21
import { effect } from "@web/core/utils/reactive" ;
22
+ import { redirect } from "@web/core/utils/urls" ;
20
23
import { standardActionServiceProps } from "@web/webclient/actions/action_service" ;
21
24
import { AddPageDialog } from "@website/components/dialog/add_page_dialog" ;
22
25
import { ResourceEditor } from "@website/components/resource_editor/resource_editor" ;
@@ -36,6 +39,7 @@ export class WebsiteBuilder extends Component {
36
39
this . websiteService = useService ( "website" ) ;
37
40
this . ui = useService ( "ui" ) ;
38
41
this . title = useService ( "title" ) ;
42
+ this . hotkeyService = useService ( "hotkey" ) ;
39
43
this . websiteService . websiteRootInstance = undefined ;
40
44
41
45
this . websiteContent = useRef ( "iframe" ) ;
@@ -44,6 +48,9 @@ export class WebsiteBuilder extends Component {
44
48
} ) ;
45
49
this . state = useState ( { isEditing : false , key : 1 } ) ;
46
50
this . websiteContext = useState ( this . websiteService . context ) ;
51
+
52
+ this . onKeydownRefresh = this . _onKeydownRefresh . bind ( this ) ;
53
+
47
54
onMounted ( ( ) => {
48
55
// You can't wait for rendering because the Builder depends on the page style synchronously.
49
56
effect (
@@ -94,6 +101,7 @@ export class WebsiteBuilder extends Component {
94
101
}
95
102
} ) ;
96
103
onMounted ( ( ) => {
104
+ this . addListeners ( document ) ;
97
105
this . addSystrayItems ( ) ;
98
106
this . websiteService . useMysterious = true ;
99
107
const { enable_editor, edit_translations } = this . props . action . context . params || { } ;
@@ -109,6 +117,27 @@ export class WebsiteBuilder extends Component {
109
117
this . websiteService . useMysterious = false ;
110
118
this . websiteService . currentWebsiteId = null ;
111
119
} ) ;
120
+
121
+ effect (
122
+ ( state ) => {
123
+ this . websiteContext . edition = state . isEditing ;
124
+ if ( ! state . isEditing ) {
125
+ this . addSystrayItems ( ) ;
126
+ }
127
+ } ,
128
+ [ this . state ]
129
+ ) ;
130
+ useEffect (
131
+ ( isEditing ) => {
132
+ document . querySelector ( "body" ) . classList . toggle ( "o_builder_open" , isEditing ) ;
133
+ if ( isEditing ) {
134
+ setTimeout ( ( ) => {
135
+ registry . category ( "systray" ) . remove ( "website.WebsiteSystrayItem" ) ;
136
+ } , 200 ) ;
137
+ }
138
+ } ,
139
+ ( ) => [ this . state . isEditing ]
140
+ ) ;
112
141
}
113
142
114
143
get menuProps ( ) {
@@ -157,15 +186,10 @@ export class WebsiteBuilder extends Component {
157
186
}
158
187
159
188
async onEditPage ( ) {
160
- document . querySelector ( "body" ) . classList . add ( "o_builder_open" ) ;
161
189
await this . iframeLoaded ;
162
190
await this . publicRootReady ;
163
191
await this . loadAssetsEditBundle ( ) ;
164
-
165
- setTimeout ( ( ) => {
166
- this . state . isEditing = true ;
167
- registry . category ( "systray" ) . remove ( "website.WebsiteSystrayItem" ) ;
168
- } , 200 ) ;
192
+ this . state . isEditing = true ;
169
193
}
170
194
171
195
async loadAssetsEditBundle ( ) {
@@ -191,7 +215,12 @@ export class WebsiteBuilder extends Component {
191
215
return ;
192
216
}
193
217
194
- if ( ! isHTTPSorNakedDomainRedirection ( iframe . contentWindow . location . origin , window . location . origin ) ) {
218
+ if (
219
+ ! isHTTPSorNakedDomainRedirection (
220
+ iframe . contentWindow . location . origin ,
221
+ window . location . origin
222
+ )
223
+ ) {
195
224
// If another domain ends up loading in the iframe (for example,
196
225
// if the iframe is being redirected and has no initial URL, so it
197
226
// loads "about:blank"), do not push that into the history
@@ -331,9 +360,7 @@ export class WebsiteBuilder extends Component {
331
360
async reloadIframeAndCloseEditor ( ) {
332
361
const isEditing = false ;
333
362
await this . reloadIframe ( isEditing ) ;
334
- document . querySelector ( "body" ) . classList . remove ( "o_builder_open" ) ;
335
363
this . state . isEditing = isEditing ;
336
- this . addSystrayItems ( ) ;
337
364
}
338
365
339
366
async reloadIframe ( isEditing = true , url ) {
@@ -371,6 +398,8 @@ export class WebsiteBuilder extends Component {
371
398
setIframeLoaded ( ) {
372
399
this . iframeLoaded = new Promise ( ( resolve ) => {
373
400
this . resolveIframeLoaded = ( ) => {
401
+ this . hotkeyService . registerIframe ( this . websiteContent . el ) ;
402
+ this . addListeners ( this . websiteContent . el . contentDocument ) ;
374
403
resolve ( this . websiteContent . el ) ;
375
404
} ;
376
405
} ) ;
@@ -390,6 +419,42 @@ export class WebsiteBuilder extends Component {
390
419
onResourceEditorResize ( width ) {
391
420
browser . localStorage . setItem ( "ace_editor_width" , width ) ;
392
421
}
422
+
423
+ /**
424
+ * Handles refreshing while the website preview is active.
425
+ * Makes it possible to stay in the backend after an F5 or CTRL-R keypress.
426
+ * Cannot be done through the hotkey service due to F5.
427
+ *
428
+ * @param {KeyboardEvent } ev
429
+ */
430
+ _onKeydownRefresh ( ev ) {
431
+ const hotkey = getActiveHotkey ( ev ) ;
432
+ if ( hotkey !== "control+r" && hotkey !== "f5" ) {
433
+ return ;
434
+ }
435
+ // The iframe isn't loaded yet: fallback to default refresh.
436
+ if ( this . websiteService . contentWindow === undefined ) {
437
+ return ;
438
+ }
439
+ ev . preventDefault ( ) ;
440
+ const path = this . websiteService . contentWindow . location ;
441
+ const debugMode = this . env . debug ? `&debug=${ this . env . debug } ` : "" ;
442
+ redirect (
443
+ `/odoo/action-website.website_preview?path=${ encodeURIComponent ( path ) } ${ debugMode } `
444
+ ) ;
445
+ }
446
+
447
+ /**
448
+ * Registers listeners on both the main document and the iframe document.
449
+ * It can mostly be done through the hotkey service, but not all keys are
450
+ * whitelisted, specifically F5 which we want to override.
451
+ *
452
+ * @param {HTMLElement } target - document or iframe document
453
+ */
454
+ addListeners ( target ) {
455
+ target . removeEventListener ( "keydown" , this . onKeydownRefresh ) ;
456
+ target . addEventListener ( "keydown" , this . onKeydownRefresh ) ;
457
+ }
393
458
}
394
459
395
460
function deleteQueryParam ( param , target = window , adaptBrowserUrl = false ) {
0 commit comments