diff --git a/scripts/langindex.json b/scripts/langindex.json index 0ed0824bc..dec428131 100644 --- a/scripts/langindex.json +++ b/scripts/langindex.json @@ -1962,5 +1962,7 @@ "core.wsfunctionnotavailable": "local_moodlemobileapp", "core.year": "moodle", "core.years": "moodle", - "core.yes": "moodle" + "core.yes": "moodle", + "core.youreoffline": "local_moodlemobileapp", + "core.youreonline": "local_moodlemobileapp" } diff --git a/src/app/app.component.ts b/src/app/app.component.ts index e9bd35add..0462ec1cc 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -14,6 +14,7 @@ import { Component, OnInit, NgZone } from '@angular/core'; import { Platform, IonicApp } from 'ionic-angular'; +import { Network } from '@ionic-native/network'; import { CoreAppProvider } from '@providers/app'; import { CoreEventsProvider } from '@providers/events'; import { CoreLangProvider } from '@providers/lang'; @@ -42,7 +43,7 @@ export class MoodleMobileApp implements OnInit { private eventsProvider: CoreEventsProvider, private loginHelper: CoreLoginHelperProvider, private zone: NgZone, private appProvider: CoreAppProvider, private langProvider: CoreLangProvider, private sitesProvider: CoreSitesProvider, private screenOrientation: ScreenOrientation, private urlSchemesProvider: CoreCustomURLSchemesProvider, - private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider) { + private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private network: Network) { this.logger = logger.getInstance('AppComponent'); platform.ready().then(() => { @@ -109,6 +110,22 @@ export class MoodleMobileApp implements OnInit { this.loginHelper.sitePolicyNotAgreed(data.siteId); }); + // Refresh online status when changes. + this.network.onchange().subscribe(() => { + // Execute the callback in the Angular zone, so change detection doesn't stop working. + this.zone.run(() => { + const isOnline = this.appProvider.isOnline(); + document.body.classList.toggle('core-offline', !isOnline); + document.body.classList.toggle('core-online', isOnline); + + if (isOnline) { + setTimeout(() => { + document.body.classList.remove('core-online'); + }, 3000); + } + }); + }); + // Check URLs loaded in any InAppBrowser. this.eventsProvider.on(CoreEventsProvider.IAB_LOAD_START, (event) => { // URLs with a custom scheme can be prefixed with "http://" or "https://", we need to remove this. diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json index 58ceb5175..748bb45f2 100644 --- a/src/assets/lang/en.json +++ b/src/assets/lang/en.json @@ -1960,5 +1960,7 @@ "core.wsfunctionnotavailable": "The web service function is not available.", "core.year": "year", "core.years": "years", - "core.yes": "Yes" + "core.yes": "Yes", + "core.youreoffline": "You are offline", + "core.youreonline": "You are back online" } \ No newline at end of file diff --git a/src/core/mainmenu/pages/menu/menu.html b/src/core/mainmenu/pages/menu/menu.html index 9ee9cf395..b23b70a49 100644 --- a/src/core/mainmenu/pages/menu/menu.html +++ b/src/core/mainmenu/pages/menu/menu.html @@ -1,5 +1,13 @@ - + +
+
+ {{ "core.youreonline" | translate }} +
+
+ {{ "core.youreoffline" | translate }} +
+
diff --git a/src/core/mainmenu/pages/menu/menu.scss b/src/core/mainmenu/pages/menu/menu.scss index a5114c071..8dfe143f8 100644 --- a/src/core/mainmenu/pages/menu/menu.scss +++ b/src/core/mainmenu/pages/menu/menu.scss @@ -1,8 +1,9 @@ ion-app.app-root page-core-mainmenu { - ion-icon { + ion-icon.tab-button-icon { text-overflow: unset; overflow: visible; text-align: center; + transition: margin 500ms ease-in-out, transform 300ms ease-in-out; } .ion-md-fa-graduation-cap, @@ -40,4 +41,56 @@ ion-app.app-root page-core-mainmenu { font-size: 23px; height: 23px; } + + .core-network-message { + position: absolute; + bottom: 0; + left: 0; + right: 0; + padding-left: 10px; + padding-right: 10px; + text-align: center; + color: white; + visibility: hidden; + height: 0; + transition: all 500ms ease-in-out; + opacity: .8; + } + + .core-online-message, + .core-offline-message { + display: none; + } +} + + +.core-online ion-app.app-root page-core-mainmenu, +.core-offline ion-app.app-root page-core-mainmenu { + + core-ion-tabs[tabsplacement="bottom"] ion-icon.tab-button-icon { + margin-bottom: $core-network-message-height / 2; + + &.icon-ios { + margin-bottom: 14px; + } + } + + .core-network-message { + visibility: visible; + height: $core-network-message-height; + pointer-events: none; + } +} + +.core-offline ion-app.app-root page-core-mainmenu .core-offline-message, +.core-online ion-app.app-root page-core-mainmenu .core-online-message { + display: block; +} + +.core-online ion-app.app-root page-core-mainmenu .core-network-message { + background: $green; +} + +.core-offline ion-app.app-root page-core-mainmenu .core-network-message { + background: $red; } diff --git a/src/lang/en.json b/src/lang/en.json index 59183bdcf..808bf5738 100644 --- a/src/lang/en.json +++ b/src/lang/en.json @@ -293,5 +293,7 @@ "wsfunctionnotavailable": "The web service function is not available.", "year": "year", "years": "years", - "yes": "Yes" + "yes": "Yes", + "youreoffline": "You are offline", + "youreonline": "You are back online" } \ No newline at end of file diff --git a/src/theme/variables.scss b/src/theme/variables.scss index f82a5a8fa..ec639ba86 100644 --- a/src/theme/variables.scss +++ b/src/theme/variables.scss @@ -188,6 +188,8 @@ $core-loading-spinner-color: $core-color !default; $core-spinner-color: $core-color !default; $core-button-outline-background-color: $white !default; +$core-network-message-height: 16px !default; + // Login. $core-login-page-background-color: radial-gradient(white, $gray-light) !default; $core-login-box-background-color: $white !default;