From fb83d971501e9128f0dfe315271a4ef387269286 Mon Sep 17 00:00:00 2001 From: Hadi Nategh Date: Mon, 19 Apr 2021 10:17:40 +0200 Subject: [PATCH] Implement loading aware framework animation --- api/js/framework/fw_base.js | 24 ++++++++++++ api/js/framework/fw_browser.js | 1 + api/src/Framework.php | 2 +- api/src/Framework/Ajax.php | 71 ++++++++++++++++++++++++++++++++++ pixelegg/css/mobile.css | 29 ++++---------- pixelegg/css/pixelegg.css | 29 ++++---------- pixelegg/css/pixelegg.less | 13 ------- pixelegg/head.tpl | 7 +++- pixelegg/js/fw_pixelegg.js | 5 ++- pixelegg/mobile/fw_mobile.css | 29 ++++---------- 10 files changed, 130 insertions(+), 80 deletions(-) diff --git a/api/js/framework/fw_base.js b/api/js/framework/fw_base.js index a9349bdaae..1d7d746fde 100644 --- a/api/js/framework/fw_base.js +++ b/api/js/framework/fw_base.js @@ -39,6 +39,9 @@ var fw_base = (function(){ "use strict"; return Class.extend( this.applications = new Object(); this.activeApp = null; + // keeps the firstload animation gauge in sync + this.firstload_animation_gauge = 0; + this.apps = null; this.tabApps = JSON.parse(egw.getSessionItem('api', 'fw_tab_apps')||null) || {}; @@ -520,6 +523,7 @@ var fw_base = (function(){ "use strict"; return Class.extend( if (_status == 5 && !_app.isFrameworkTab) _app.tab.hideTabHeader(true); } + if (this.activeApp && this.activeApp.appName != _app.appName) this.firstload_animation(_app.appName); }, /** @@ -1347,5 +1351,25 @@ var fw_base = (function(){ "use strict"; return Class.extend( }) egw.setSessionItem('api', 'darkmode',state); egw.json('EGroupware\\Api\\Framework\\Ajax::ajax_set_darkmode_flag',[state]).sendRequest(); + }, + + /** + * firstload animation + * @param string _app app name + * @param int _gauge 0 - 100 + */ + firstload_animation: function(_app, _gauge) + { + if (_app) + { + jQuery('.fl_app.'+_app).css({ + opacity: 1 + }); + } + let progress = jQuery('.fl_progress'); + let gauge = progress.children(); + + this.firstload_animation_gauge = _gauge ? _gauge : (this.firstload_animation_gauge == 0 ? 10 : (this.firstload_animation_gauge+5)); + gauge.width(this.firstload_animation_gauge+"%"); } });}).call(this); diff --git a/api/js/framework/fw_browser.js b/api/js/framework/fw_browser.js index f1a90c55b5..adbd53c02d 100644 --- a/api/js/framework/fw_browser.js +++ b/api/js/framework/fw_browser.js @@ -165,6 +165,7 @@ var fw_browser = (function(){ "use strict"; return Class.extend( },5000); this.loadingDeferred.always(function() { + framework.firstload_animation(self.app.appName); if(self.ajaxLoaderDiv) { diff --git a/api/src/Framework.php b/api/src/Framework.php index 68ff8556eb..eadebfe4f9 100644 --- a/api/src/Framework.php +++ b/api/src/Framework.php @@ -841,7 +841,7 @@ abstract class Framework extends Framework\Extra */ protected static function _get_navbar_apps() { - $first = key($GLOBALS['egw_info']['user']['apps']); + $first = key((array)$GLOBALS['egw_info']['user']['apps']); if(is_array($GLOBALS['egw_info']['user']['apps']['admin']) && $first != 'admin') { $newarray['admin'] = $GLOBALS['egw_info']['user']['apps']['admin']; diff --git a/api/src/Framework/Ajax.php b/api/src/Framework/Ajax.php index c990407a36..c9c55243ec 100755 --- a/api/src/Framework/Ajax.php +++ b/api/src/Framework/Ajax.php @@ -252,6 +252,11 @@ abstract class Ajax extends Api\Framework $extra['check-framework'] = $_GET['cd'] !== 'no' && $GLOBALS['egw_info']['flags']['nonavbar'] !== 'popup'; } } + + //add loader animation + $this->tpl->set_var('firstload_animation', $this->_get_firstload_animation()); + $this->tpl->set_var('firstload_animation_style', $this->_get_firstload_animation_style()); + // allow apps to load JavaScript or CSS files, knowing we're loading the framework or not Api\Hooks::process(array( 'location' => 'framework_header', @@ -367,6 +372,72 @@ abstract class Ajax extends Api\Framework $this->topmenu_items[] = ''.$title.''; } + /** + * set style for firstload animation + * @return string + */ + private function _get_firstload_animation_style() + { + return ' + #egw_fw_firstload .fl_app { + opacity:0.3; + width: 50px; + height:50px; + background-repeat: no-repeat; + clip-path: polygon(100% 9%, 73% 4%, 67% 3%, 63% 2%, 56% 1%, 48% 0, 41% 1%, 33% 3%, 26% 6%, 21% 9%, 16% 13%, + 11% 19%, 7% 24%, 4% 30%, 1% 38%, 0 46%, 0 53%, 1% 61%, 3% 67%, 5% 72%, 8% 77%, 12% 83%, 16% 87%, 21% 91%, + 27% 95%, 32% 97%, 39% 99%, 46% 100%, 53% 100%, 60% 99%, 67% 97%, 74% 94%, 79% 91%, 85% 86%, 90% 81%, + 94% 74%, 97% 67%, 98% 58%); + background-color: #b0dccc; + transition: opacity 1s cubic-bezier(0.4, 0, 1, 1); + } + #egw_fw_firstload .fl_apps { + width: 100%; + max-width: 400px; + display: block; + background: transparent; + margin: 35% auto 20px; + } + #egw_fw_firstload .fl_wrapper { + margin:auto; + width:40%; + } + #egw_fw_firstload .fl_progress { + width: 100%; + height: 5px; + border: 1px solid #b1dccc; + border-radius: 5px; + } + #egw_fw_firstload .fl_progress div{ + width: 0%; + height: 5px; + background-color: #005d8b; + transition: width 0.2s linear; + } + '; + } + + /** + * get firstload animation content + * @return string + */ + private function _get_firstload_animation() + { + $content = $appsDiv = ''; + $apps = array_filter($this->navbar_apps(), static function($a){ + if (!in_array($a['name'], ['about', 'wiki', 'devtools', 'preferences'])) return $a; + }); + foreach ($apps as $app) + { + $appsDiv .= '
'; + } + $content .= '
'.$appsDiv. + '
'; + return $content; + } + /** * Add info items to the topmenu template class to be displayed * diff --git a/pixelegg/css/mobile.css b/pixelegg/css/mobile.css index f19660d51d..047ee488d6 100644 --- a/pixelegg/css/mobile.css +++ b/pixelegg/css/mobile.css @@ -134,7 +134,7 @@ } html[data-darkmode='1'] #mail_sidebox_header.egw_fw_ui_sidemenu_entry_header_active, html[data-darkmode='1'] #mail_sidebox_header { - border-color: #5db9ec!important; + border-color: #5db9ec !important; } html[data-darkmode='1'] #egw_fw_main #egw_fw_tabs .egw_fw_ui_tabs_header #mail-egw_fw_ui_tab_header.egw_fw_ui_tab_header_active { border-top-color: #5db9ec !important; @@ -1515,20 +1515,20 @@ span.ui-icon-search { box-shadow: -2px 1px 9px 3px #B4B4B4; } .ui-dialog .ui-dialog-buttonpane { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; padding-top: 0.7em; } .ui-dialog .ui-dialog-titlebar { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; font-size: 12pt; border: none; font-weight: normal; background: white; } .ui-dialog .ui-dialog-titlebar-close { - right: .8em; + right: 0.8em; } .ui-widget-content { border: 1px solid #B4B4B4; @@ -6336,7 +6336,7 @@ a.textSidebox { } } .egw-loading-prompt-container::before { - opacity: .3; + opacity: 0.3; content: ""; background-color: #aaaaaa; width: 100%; @@ -6415,7 +6415,7 @@ a.textSidebox { z-index: 999; width: 100px; border-radius: 5px; - border: solid 10px #679FD2; + border: solid 10px #679FD2; transform: translate(-50%, -50%); } /** @@ -6782,19 +6782,6 @@ table.egwGridView_grid img.et2_appicon { height: 100%; width: 100%; } -#egw_fw_firstload:before { - content: ""; - display: inline-block; - position: absolute; - width: 100%; - height: 100%; - background-image: url(../../pixelegg/images/loading.svg); - background-position: center; - background-repeat: no-repeat; - -webkit-animation: fw-firstload 2s infinite; - animation: fw-firstload 2s infinite; - -moz-animation: fw-firstload 2s infinite; -} #egw_fw_sidebar #egw_fw_sidemenu #addressbook_sidebox_content .egw_fw_ui_category_active { background-color: #003366 !important; } diff --git a/pixelegg/css/pixelegg.css b/pixelegg/css/pixelegg.css index cc21ea926a..6bd4f40ea4 100644 --- a/pixelegg/css/pixelegg.css +++ b/pixelegg/css/pixelegg.css @@ -124,7 +124,7 @@ } html[data-darkmode='1'] #mail_sidebox_header.egw_fw_ui_sidemenu_entry_header_active, html[data-darkmode='1'] #mail_sidebox_header { - border-color: #5db9ec!important; + border-color: #5db9ec !important; } html[data-darkmode='1'] #egw_fw_main #egw_fw_tabs .egw_fw_ui_tabs_header #mail-egw_fw_ui_tab_header.egw_fw_ui_tab_header_active { border-top-color: #5db9ec !important; @@ -1505,20 +1505,20 @@ span.ui-icon-search { box-shadow: -2px 1px 9px 3px #B4B4B4; } .ui-dialog .ui-dialog-buttonpane { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; padding-top: 0.7em; } .ui-dialog .ui-dialog-titlebar { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; font-size: 12pt; border: none; font-weight: normal; background: white; } .ui-dialog .ui-dialog-titlebar-close { - right: .8em; + right: 0.8em; } .ui-widget-content { border: 1px solid #B4B4B4; @@ -6326,7 +6326,7 @@ a.textSidebox { } } .egw-loading-prompt-container::before { - opacity: .3; + opacity: 0.3; content: ""; background-color: #aaaaaa; width: 100%; @@ -6405,7 +6405,7 @@ a.textSidebox { z-index: 999; width: 100px; border-radius: 5px; - border: solid 10px #679FD2; + border: solid 10px #679FD2; transform: translate(-50%, -50%); } /** @@ -6772,19 +6772,6 @@ table.egwGridView_grid img.et2_appicon { height: 100%; width: 100%; } -#egw_fw_firstload:before { - content: ""; - display: inline-block; - position: absolute; - width: 100%; - height: 100%; - background-image: url(../../pixelegg/images/loading.svg); - background-position: center; - background-repeat: no-repeat; - -webkit-animation: fw-firstload 2s infinite; - animation: fw-firstload 2s infinite; - -moz-animation: fw-firstload 2s infinite; -} #egw_fw_sidebar #egw_fw_sidemenu #addressbook_sidebox_content .egw_fw_ui_category_active { background-color: #003366 !important; } diff --git a/pixelegg/css/pixelegg.less b/pixelegg/css/pixelegg.less index 47c63c833b..aa52836f8f 100644 --- a/pixelegg/css/pixelegg.less +++ b/pixelegg/css/pixelegg.less @@ -24,19 +24,6 @@ background: white; height: 100%; width: 100%; - &:before{ - content:""; - display: inline-block; - position: absolute; - width: 100%; - height: 100%; - background-image: url(../../pixelegg/images/loading.svg); - background-position: center; - background-repeat: no-repeat; - -webkit-animation: fw-firstload 2s infinite; - animation: fw-firstload 2s infinite; - -moz-animation: fw-firstload 2s infinite; - } } #egw_fw_sidebar { #egw_fw_sidemenu { diff --git a/pixelegg/head.tpl b/pixelegg/head.tpl index 05e21fc9dd..d9ee5d7a76 100644 --- a/pixelegg/head.tpl +++ b/pixelegg/head.tpl @@ -21,6 +21,9 @@ + {java_script} @@ -55,5 +58,7 @@
-
+
+ {firstload_animation} +
diff --git a/pixelegg/js/fw_pixelegg.js b/pixelegg/js/fw_pixelegg.js index d61dd53f05..430f2c1c63 100644 --- a/pixelegg/js/fw_pixelegg.js +++ b/pixelegg/js/fw_pixelegg.js @@ -70,6 +70,7 @@ */ et2_loadingFinished: function() { this._super.apply(this, arguments); + framework.firstload_animation('', 100); setTimeout(function(){jQuery('#egw_fw_firstload').remove();}, 1000); }, @@ -119,8 +120,8 @@ } jQuery(document).ready(function() { - //Stop the loading animation after 3sec if for whatever reason it didn't end - setTimeout(function(){jQuery('#egw_fw_firstload').remove();}, 3000); + //Stop the loading animation after 5sec if for whatever reason it didn't end + setTimeout(function(){jQuery('#egw_fw_firstload').remove();}, 5000); window.framework = new fw_pixelegg("egw_fw_sidemenu", "egw_fw_tabs", window.egw_webserverUrl, egw_setSideboxSize,"egw_fw_splitter", 255, 245); // should be identical to jdots_framework::(DEFAULT|MIN)_SIDEBAR_WIDTH window.callManual = window.framework.callManual; diff --git a/pixelegg/mobile/fw_mobile.css b/pixelegg/mobile/fw_mobile.css index 7168d4624b..b29fa280af 100644 --- a/pixelegg/mobile/fw_mobile.css +++ b/pixelegg/mobile/fw_mobile.css @@ -99,7 +99,7 @@ } html[data-darkmode='1'] #mail_sidebox_header.egw_fw_ui_sidemenu_entry_header_active, html[data-darkmode='1'] #mail_sidebox_header { - border-color: #5db9ec!important; + border-color: #5db9ec !important; } html[data-darkmode='1'] #egw_fw_main #egw_fw_tabs .egw_fw_ui_tabs_header #mail-egw_fw_ui_tab_header.egw_fw_ui_tab_header_active { border-top-color: #5db9ec !important; @@ -1526,20 +1526,20 @@ span.ui-icon-search { box-shadow: -2px 1px 9px 3px #B4B4B4; } .ui-dialog .ui-dialog-buttonpane { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; padding-top: 0.7em; } .ui-dialog .ui-dialog-titlebar { - padding-left: .8em; - padding-right: .8em; + padding-left: 0.8em; + padding-right: 0.8em; font-size: 12pt; border: none; font-weight: normal; background: white; } .ui-dialog .ui-dialog-titlebar-close { - right: .8em; + right: 0.8em; } .ui-widget-content { border: 1px solid #B4B4B4; @@ -6347,7 +6347,7 @@ a.textSidebox { } } .egw-loading-prompt-container::before { - opacity: .3; + opacity: 0.3; content: ""; background-color: #aaaaaa; width: 100%; @@ -6426,7 +6426,7 @@ a.textSidebox { z-index: 999; width: 100px; border-radius: 5px; - border: solid 10px #679FD2; + border: solid 10px #679FD2; transform: translate(-50%, -50%); } /** @@ -6590,19 +6590,6 @@ span.egw_tutorial_title { height: 100%; width: 100%; } -#egw_fw_firstload:before { - content: ""; - display: inline-block; - position: absolute; - width: 100%; - height: 100%; - background-image: url(../../pixelegg/images/loading.svg); - background-position: center; - background-repeat: no-repeat; - -webkit-animation: fw-firstload 2s infinite; - animation: fw-firstload 2s infinite; - -moz-animation: fw-firstload 2s infinite; -} #egw_fw_sidebar #egw_fw_sidemenu #addressbook_sidebox_content .egw_fw_ui_category_active { background-color: #003366 !important; }