@@ -59,6 +59,7 @@ define(function (require, exports, module) {
5959 Metrics = require ( "utils/Metrics" ) ,
6060 LiveDevelopment = require ( "LiveDevelopment/main" ) ,
6161 LiveDevServerManager = require ( "LiveDevelopment/LiveDevServerManager" ) ,
62+ MultiBrowserLiveDev = require ( "LiveDevelopment/LiveDevMultiBrowser" ) ,
6263 NativeApp = require ( "utils/NativeApp" ) ,
6364 StringUtils = require ( "utils/StringUtils" ) ,
6465 FileSystem = require ( "filesystem/FileSystem" ) ,
@@ -157,6 +158,13 @@ define(function (require, exports, module) {
157158 // so that when user unclicks the button we can revert back to the mode that was originally selected
158159 let modeThatWasSelected = null ;
159160
161+ // live Preview overlay variables (overlays are shown when live preview is connecting or there's a syntax error)
162+ let $overlayContainer = null ; // the overlay container
163+ let shouldShowSyncErrorOverlay = true ; // once user closes the overlay we don't show them again
164+ let shouldShowConnectingOverlay = true ;
165+ let connectingOverlayTimer = null ; // this is needed as we show the connecting overlay after 3s
166+ let connectingOverlayTimeDuration = 3000 ;
167+
160168 StaticServer . on ( EVENT_EMBEDDED_IFRAME_WHO_AM_I , function ( ) {
161169 if ( $iframe && $iframe [ 0 ] ) {
162170 const iframeDom = $iframe [ 0 ] ;
@@ -172,6 +180,111 @@ define(function (require, exports, module) {
172180 editor . focus ( ) ;
173181 } ) ;
174182
183+ /**
184+ * this function is responsible to check whether to show the overlay or not and how it should be shown
185+ * because if user has closed the overlay manually, we don't show it again
186+ * secondly, for connecting overlay we show that after a 3s timer, but sync error overlay is shown immediately
187+ * @param {String } textMessage - the text that is written inside the overlay
188+ * @param {Number } status - 1 for connect, 4 for sync error but we match it using MultiBrowserLiveDev
189+ */
190+ function _handleOverlay ( textMessage , status ) {
191+ if ( ! $panel ) { return ; }
192+
193+ // remove any existing overlay & timer
194+ _hideOverlay ( ) ;
195+
196+ // to not show the overlays if user has already closed it before
197+ if ( status === MultiBrowserLiveDev . STATUS_CONNECTING && ! shouldShowConnectingOverlay ) { return ; }
198+ if ( status === MultiBrowserLiveDev . STATUS_SYNC_ERROR && ! shouldShowSyncErrorOverlay ) { return ; }
199+
200+ // for connecting status, we delay showing the overlay by 3 seconds
201+ if ( status === MultiBrowserLiveDev . STATUS_CONNECTING ) {
202+ connectingOverlayTimer = setTimeout ( ( ) => {
203+ _createAndShowOverlay ( textMessage , status ) ;
204+ connectingOverlayTimer = null ;
205+ } , connectingOverlayTimeDuration ) ;
206+ return ;
207+ }
208+
209+ // for sync error status, show immediately
210+ _createAndShowOverlay ( textMessage , status ) ;
211+ }
212+
213+ /**
214+ * this function is responsible to create & show the overlay.
215+ * so overlay is shown when the live preview is connecting or live preview stopped because of some syntax error
216+ * @param {String } textMessage - the text that is written inside the overlay
217+ * @param {Number } status - 1 for connect, 4 for sync error but we match it using MultiBrowserLiveDev
218+ */
219+ function _createAndShowOverlay ( textMessage , status ) {
220+ if ( ! $panel ) { return ; }
221+
222+ // create the overlay element
223+ // styled inside the 'live-preview.css'
224+ $overlayContainer = $ ( "<div>" ) . addClass ( "live-preview-status-overlay" ) ; // the wrapper for overlay element
225+ const $message = $ ( "<div>" ) . addClass ( "live-preview-overlay-message" ) . text ( textMessage ) ;
226+
227+ // the close button at the right end of the overlay
228+ const $close = $ ( "<div>" ) . addClass ( "live-preview-overlay-close" )
229+ . attr ( "title" , Strings . LIVE_PREVIEW_HIDE_OVERLAY )
230+ . on ( 'click' , ( ) => {
231+ if ( status === MultiBrowserLiveDev . STATUS_CONNECTING ) {
232+ shouldShowConnectingOverlay = false ;
233+ } else if ( status === MultiBrowserLiveDev . STATUS_SYNC_ERROR ) {
234+ shouldShowSyncErrorOverlay = false ;
235+ }
236+ _hideOverlay ( ) ;
237+ } ) ;
238+ const $closeIcon = $ ( "<i>" ) . addClass ( "fas fa-times" ) ;
239+
240+ $close . append ( $closeIcon ) ;
241+ $overlayContainer . append ( $message ) ;
242+ $overlayContainer . append ( $close ) ;
243+ $panel . append ( $overlayContainer ) ;
244+ }
245+
246+ /**
247+ * responsible to hide the overlay
248+ */
249+ function _hideOverlay ( ) {
250+ _clearConnectingOverlayTimer ( ) ;
251+ if ( $overlayContainer ) {
252+ $overlayContainer . remove ( ) ;
253+ $overlayContainer = null ;
254+ }
255+ }
256+
257+ /**
258+ * This is a helper function that just checks that if connectingOverlayTimer exists, we clear it
259+ */
260+ function _clearConnectingOverlayTimer ( ) {
261+ if ( connectingOverlayTimer ) {
262+ clearTimeout ( connectingOverlayTimer ) ;
263+ connectingOverlayTimer = null ;
264+ }
265+ }
266+
267+ /**
268+ * this function adds/remove the full-width class from the overlay container
269+ * styled inside 'live-preview.css'
270+ *
271+ * we need this because
272+ * normally when live preview has a good width (more than 305px) then a 3px divider is shown at the left end
273+ * so in that case we give the overlay a width of (100% - 3px),
274+ * but when the live preview width is reduced
275+ * then that divider line gets cut off, so in that case we make the width 100% for this overlay
276+ *
277+ * without this handling, a white gap appears on the left side, which is distracting
278+ */
279+ function _setOverlayWidth ( ) {
280+ if ( ! $overlayContainer || ! $panel || ! $panel . length ) { return ; }
281+ if ( $panel . width ( ) <= 305 ) {
282+ $overlayContainer . addClass ( "full-width" ) ;
283+ } else {
284+ $overlayContainer . removeClass ( "full-width" ) ;
285+ }
286+ }
287+
175288 function _showProFeatureDialog ( ) {
176289 const dialog = Dialogs . showModalDialog (
177290 DefaultDialogs . DIALOG_ID_INFO ,
@@ -743,6 +856,10 @@ define(function (require, exports, module) {
743856 _loadPreview ( true , true ) ;
744857 Metrics . countEvent ( Metrics . EVENT_TYPE . LIVE_PREVIEW , "reloadBtn" , "click" ) ;
745858 } ) ;
859+
860+ // Set up ResizeObserver for overlay width adjustments
861+ // to understand why we're doing this read _setOverlayWidth function
862+ new ResizeObserver ( _setOverlayWidth ) . observe ( $panel [ 0 ] ) ;
746863 }
747864
748865 async function _loadPreview ( force , isReload ) {
@@ -920,12 +1037,27 @@ define(function (require, exports, module) {
9201037 }
9211038 }
9221039
923- function _activeDocChanged ( ) {
1040+ function _activeDocChanged ( event , focusedEditor , lostEditor ) {
9241041 if ( ! LivePreviewSettings . isUsingCustomServer ( ) && ! LiveDevelopment . isActive ( )
9251042 && ( panel . isVisible ( ) || StaticServer . hasActiveLivePreviews ( ) ) ) {
9261043 // we do this only once after project switch if live preview for a doc is not active.
9271044 LiveDevelopment . openLivePreview ( ) ;
9281045 }
1046+
1047+ // we hide the overlay when there's no editor or its a non-previewable file
1048+ if ( ! focusedEditor || ! focusedEditor . document ) {
1049+ _hideOverlay ( ) ;
1050+ return ;
1051+ }
1052+
1053+ const filePath = focusedEditor . document . file . fullPath ;
1054+ const isPreviewable = utils . isPreviewableFile ( filePath ) || utils . isServerRenderedFile ( filePath ) ;
1055+ const customServeURL = LivePreviewSettings . isUsingCustomServer ( ) &&
1056+ LivePreviewSettings . getCustomServerConfig ( filePath ) ;
1057+
1058+ if ( ! isPreviewable && ! customServeURL ) {
1059+ _hideOverlay ( ) ;
1060+ }
9291061 }
9301062
9311063 /**
@@ -948,6 +1080,13 @@ define(function (require, exports, module) {
9481080 console . error ( "Live preview URLs differ between phoenix live preview extension and core live preview" ,
9491081 currentPreviewDetails , previewDetails ) ;
9501082 }
1083+
1084+ const status = MultiBrowserLiveDev . status ;
1085+ if ( status === MultiBrowserLiveDev . STATUS_CONNECTING ) {
1086+ _handleOverlay ( Strings . LIVE_DEV_STATUS_TIP_PROGRESS1 , status ) ;
1087+ } else if ( status === MultiBrowserLiveDev . STATUS_SYNC_ERROR ) {
1088+ _handleOverlay ( Strings . LIVE_DEV_STATUS_TIP_SYNC_ERROR , status ) ;
1089+ }
9511090 }
9521091
9531092 async function _currentFileChanged ( _event , changedFile ) {
@@ -1171,6 +1310,16 @@ define(function (require, exports, module) {
11711310 _loadPreview ( true ) ;
11721311 } ) ;
11731312
1313+ MultiBrowserLiveDev . on ( MultiBrowserLiveDev . EVENT_STATUS_CHANGE , function ( event , status ) {
1314+ if ( status === MultiBrowserLiveDev . STATUS_CONNECTING ) {
1315+ _handleOverlay ( Strings . LIVE_DEV_STATUS_TIP_PROGRESS1 , status ) ;
1316+ } else if ( status === MultiBrowserLiveDev . STATUS_SYNC_ERROR ) {
1317+ _handleOverlay ( Strings . LIVE_DEV_STATUS_TIP_SYNC_ERROR , status ) ;
1318+ } else {
1319+ _hideOverlay ( ) ;
1320+ }
1321+ } ) ;
1322+
11741323 function refreshPreview ( ) {
11751324 StaticServer . getPreviewDetails ( ) . then ( ( previewDetails ) => {
11761325 _openReadmeMDIfFirstTime ( ) ;
0 commit comments