diff --git a/src/app/components/components.module.ts b/src/app/components/components.module.ts
index afc95a694..b16efbbcb 100644
--- a/src/app/components/components.module.ts
+++ b/src/app/components/components.module.ts
@@ -20,6 +20,7 @@ import { TranslateModule } from '@ngx-translate/core';
import { CoreIconComponent } from './icon/icon';
import { CoreLoadingComponent } from './loading/loading';
import { CoreShowPasswordComponent } from './show-password/show-password';
+import { CoreEmptyBoxComponent } from './empty-box/empty-box';
import { CoreDirectivesModule } from '@app/directives/directives.module';
import { CorePipesModule } from '@app/pipes/pipes.module';
@@ -28,6 +29,7 @@ import { CorePipesModule } from '@app/pipes/pipes.module';
CoreIconComponent,
CoreLoadingComponent,
CoreShowPasswordComponent,
+ CoreEmptyBoxComponent,
],
imports: [
CommonModule,
@@ -40,6 +42,7 @@ import { CorePipesModule } from '@app/pipes/pipes.module';
CoreIconComponent,
CoreLoadingComponent,
CoreShowPasswordComponent,
+ CoreEmptyBoxComponent,
],
})
export class CoreComponentsModule {}
diff --git a/src/app/components/empty-box/core-empty-box.html b/src/app/components/empty-box/core-empty-box.html
new file mode 100644
index 000000000..b15958be0
--- /dev/null
+++ b/src/app/components/empty-box/core-empty-box.html
@@ -0,0 +1,9 @@
+
+
+
![]()
+
+
+
{{ message }}
+
+
+
diff --git a/src/app/components/empty-box/empty-box.scss b/src/app/components/empty-box/empty-box.scss
new file mode 100644
index 000000000..9fea08738
--- /dev/null
+++ b/src/app/components/empty-box/empty-box.scss
@@ -0,0 +1,70 @@
+:host {
+ .core-empty-box {
+ position: absolute;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ display: table;
+ height: 100%;
+ width: 100%;
+ margin: 0;
+ clear: both;
+ pointer-events: none;
+
+ .core-empty-box-content {
+ margin: 0;
+ display: table-cell;
+ text-align: center;
+ vertical-align: middle;
+ pointer-events: auto;
+ }
+
+ &.core-empty-box-inline {
+ position: relative;
+ z-index: initial;
+ top: initial;
+ right: initial;
+ bottom: 0;
+ left: initial;
+ height: auto;
+ }
+
+ ion-icon {
+ font-size: 120px;
+ }
+ img {
+ height: 125px;
+ width: 145px;
+ margin: 0 auto;
+ }
+ p {
+ font-size: 120%;
+ }
+ }
+
+ &.core-empty-box-clickable .core-empty-box {
+ z-index: 0;
+ }
+
+ @media (max-width: 350px) {
+ .core-empty-box {
+ position: relative;
+ height: auto;
+ margin-top: 50px;
+
+ ion-icon {
+ font-size: 100px;
+ }
+ img {
+ height: 104px;
+ width: 121px;
+ }
+ }
+ }
+}
+
+:host-context(core-block-course-blocks) .core-empty-box {
+ position: relative;
+}
+
diff --git a/src/app/components/empty-box/empty-box.ts b/src/app/components/empty-box/empty-box.ts
new file mode 100644
index 000000000..f2d5ef172
--- /dev/null
+++ b/src/app/components/empty-box/empty-box.ts
@@ -0,0 +1,43 @@
+// (C) Copyright 2015 Moodle Pty Ltd.
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+import { Component, Input } from '@angular/core';
+
+/**
+ * Component to show an empty box message. It will show an optional icon or image and a text centered on page.
+ *
+ * Use class="core-empty-box-clickable" if you want to add some clickable elements to the box.
+ *
+ * Usage:
+ *
+ */
+@Component({
+ selector: 'core-empty-box',
+ templateUrl: 'core-empty-box.html',
+ styleUrls: ['empty-box.scss'],
+})
+export class CoreEmptyBoxComponent {
+
+ @Input() message = ''; // Message to display.
+ @Input() icon?: string; // Name of the icon to use.
+ @Input() image?: string; // Image source. If an icon is provided, image won't be used.
+
+ /**
+ * If this has to be shown inline instead of occupying whole page.
+ * If image or icon is not supplied, it's true by default.
+ */
+ @Input() inline?: boolean;
+ @Input() flipIconRtl?: boolean; // Whether to flip the icon in RTL. Defaults to false.
+
+}
diff --git a/src/app/components/icon/icon.scss b/src/app/components/icon/icon.scss
index 99a0a14ee..93c842fce 100644
--- a/src/app/components/icon/icon.scss
+++ b/src/app/components/icon/icon.scss
@@ -123,31 +123,3 @@
}
}
}
-
-// TODO ionic 5
-:host-context([dir=rtl]) ion-icon {
- &.core-icon-dir-flip,
- &.fa-caret-right,
- &.ion-md-send, &.ion-ios-send {
- -webkit-transform: scale(-1, 1);
- transform: scale(-1, 1);
- }
-}
-
-:host {
- &.icon-slash {
- &::after {
- content: " ";
- position: absolute;
- top: 0;
- bottom: 0;
- left: 0;
- right: 0;
- background-color: var(--ion-color-danger);
- -webkit-mask: url("/assets/fonts/font-awesome/solid/slash.svg") no-repeat 50% 50%;
- mask: url("/assets/fonts/font-awesome/solid/slash.svg") no-repeat 50% 50%;
- -webkit-transform: scale(-1, 1);
- transform: scale(-1, 1);
- }
- }
-}
diff --git a/src/app/components/icon/icon.ts b/src/app/components/icon/icon.ts
index c9a36fd21..4d181a0a5 100644
--- a/src/app/components/icon/icon.ts
+++ b/src/app/components/icon/icon.ts
@@ -20,6 +20,7 @@ import { Component, Input, OnChanges, ElementRef, SimpleChange } from '@angular/
* the component will detect it.
*
* Check available icons at https://fontawesome.com/icons?d=gallery&m=free
+ *
* @deprecated since 3.9.3. Please use instead.
*/
@Component({
@@ -81,9 +82,9 @@ export class CoreIconComponent implements OnChanges {
}
if (this.isTrueProperty(this.flipRtl)) {
- iconElement.classList.add('core-icon-dir-flip');
+ iconElement.classList.add('icon-flip-rtl');
} else {
- iconElement.classList.remove('core-icon-dir-flip');
+ iconElement.classList.remove('icon-flip-rtl');
}
if (this.isTrueProperty(this.fixedWidth)) {
@@ -96,10 +97,10 @@ export class CoreIconComponent implements OnChanges {
/**
* Check if the value is true or on.
*
- * @param val value to be checked.
+ * @param val Value to be checked.
* @return If has a value equivalent to true.
*/
- isTrueProperty(val: any): boolean {
+ isTrueProperty(val: unknown): boolean {
if (typeof val === 'string') {
val = val.toLowerCase().trim();
diff --git a/src/app/components/loading/core-loading.html b/src/app/components/loading/core-loading.html
index da4887db0..986f383f9 100644
--- a/src/app/components/loading/core-loading.html
+++ b/src/app/components/loading/core-loading.html
@@ -1,10 +1,10 @@
-
\ No newline at end of file
+
diff --git a/src/app/components/loading/loading.scss b/src/app/components/loading/loading.scss
index afe335a58..b8289607b 100644
--- a/src/app/components/loading/loading.scss
+++ b/src/app/components/loading/loading.scss
@@ -1,67 +1,43 @@
-ion-app.app-root {
- core-loading {
- // @todo @include core-transition(height, 200ms);
+:host {
+ position: static;
+ -webkit-transition: height 200ms ease-in-out;
+ transition: height 200ms ease-in-out;
- .core-loading-container {
- width: 100%;
+ > .core-loading-container {
+ position: absolute;
+ top: 0;
+ right: 0;
+ left: 0;
+ bottom: 0;
+ display: table;
+ height: 100%;
+ width: 100%;
+ text-align: center;
+ clear: both;
+ z-index: 3;
+ margin: 0;
+ padding: 10px 0 0 0;
+ background-color: rgba(255, 255, 255, 0.26);
+ -webkit-transition: all 200ms ease-in-out;
+ transition: all 200ms ease-in-out;
+
+ .core-loading-spinner {
+ display: table-cell;
text-align: center;
- padding-top: 10px;
- clear: both;
- /* @todo @include darkmode() {
- color: $core-dark-text-color;
- } */
- }
-
- .core-loading-content {
- display: inline;
- padding-bottom: 1px; /* This makes height be real */
- }
-
- &.core-loading-noheight .core-loading-content {
- height: auto;
- }
-
- &.safe-area-page {
- padding-left: 0 !important;
- padding-right: 0 !important;
-
- > .core-loading-content > *:not[padding],
- > .core-loading-content-loading > *:not[padding] {
- // @todo @include safe-area-padding-horizontal(0px, 0px);
- }
+ vertical-align: middle;
}
}
- .scroll-content > core-loading,
- ion-content > .scroll-content > core-loading,
- core-tab core-loading,
- .core-loading-center {
- position: static !important;
+ .core-loading-content {
+ display: inline;
+ padding-bottom: 1px; /* This makes height be real */
}
- .scroll-content > core-loading,
- ion-content > .scroll-content > core-loading,
- core-tab core-loading,
- .core-loading-center,
- core-loading.core-loading-loaded {
+ &.core-loading-noheight .core-loading-content {
+ height: auto;
+ }
+
+ &.core-loading-loaded {
position: relative;
-
- > .core-loading-container {
- position: absolute;
- // @todo @include position(0, 0, 0, 0);
- display: table;
- height: 100%;
- width: 100%;
- z-index: 1;
- margin: 0;
- padding: 0;
- clear: both;
-
- .core-loading-spinner {
- display: table-cell;
- text-align: center;
- vertical-align: middle;
- }
- }
}
}
diff --git a/src/app/components/show-password/core-show-password.html b/src/app/components/show-password/core-show-password.html
index d90db3f49..ef0ac0ce1 100644
--- a/src/app/components/show-password/core-show-password.html
+++ b/src/app/components/show-password/core-show-password.html
@@ -1,4 +1,4 @@
-
-
-
+
+
+
diff --git a/src/app/components/show-password/show-password.scss b/src/app/components/show-password/show-password.scss
index 26188a26b..1f98c810c 100644
--- a/src/app/components/show-password/show-password.scss
+++ b/src/app/components/show-password/show-password.scss
@@ -1,38 +1,35 @@
-ion-app.app-root core-show-password {
- padding: 0px;
- width: 100%;
- position: relative;
+:host {
+ display: contents;
- ion-input input.text-input {
- // @todo @include padding(null, 47px, null, null);
- }
-
- .button[icon-only] {
+ ion-button {
background: transparent;
- // @todo padding: 0 ($content-padding / 2);
+ padding: 0 calc(var(--padding-start) / 2);
position: absolute;
- // @todo @include position(null, 0, $content-padding / 2, null);
+ right: 0;
+ bottom: calc(var(--padding-bottom) / 2);
margin-top: 0;
margin-bottom: 0;
- }
-
- .core-ioninput-password {
- padding-top: 0;
- padding-bottom: 0;
+ z-index: 3;
}
}
-ion-app.app-root.md {
- .item-label-stacked core-show-password .button[icon-only] {
- bottom: 0;
- }
+::slotted(ion-input) {
+ --padding-end: 47px !important;
}
-ion-app.app-root.ios {
- .item-label-stacked core-show-password .button[icon-only] {
- bottom: -5px;
- }
- core-show-password .button[icon-only] {
- bottom: 0;
- }
+:host-context([dir="rtl"]) ion-button {
+ left: 0;
+ right: unset;
+}
+
+:host-context(.md.item-label.stacked) ion-button {
+ bottom: 0;
+}
+
+:host-context(.iositem-label.stacked) ion-button {
+ bottom: -5px;
+}
+
+:host-context(.ios) ion-button {
+ bottom: 0;
}
diff --git a/src/app/components/show-password/show-password.ts b/src/app/components/show-password/show-password.ts
index 6cec76522..d90cf3615 100644
--- a/src/app/components/show-password/show-password.ts
+++ b/src/app/components/show-password/show-password.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { Component, OnInit, AfterViewInit, Input, ElementRef, ContentChild } from '@angular/core';
+import { Component, OnInit, AfterViewInit, Input, ElementRef, ContentChild, ViewEncapsulation } from '@angular/core';
import { IonInput } from '@ionic/angular';
import { CoreApp } from '@services/app';
@@ -29,7 +29,7 @@ import { CoreUtils } from '@services/utils/utils';
*
* Example:
*
- *
+ *
*
*
*/
@@ -37,6 +37,7 @@ import { CoreUtils } from '@services/utils/utils';
selector: 'core-show-password',
templateUrl: 'core-show-password.html',
styleUrls: ['show-password.scss'],
+ encapsulation: ViewEncapsulation.ShadowDom,
})
export class CoreShowPasswordComponent implements OnInit, AfterViewInit {
diff --git a/src/app/core/courses/courses.module.ts b/src/app/core/courses/courses.module.ts
index 38449fa0a..4dd76b82a 100644
--- a/src/app/core/courses/courses.module.ts
+++ b/src/app/core/courses/courses.module.ts
@@ -14,17 +14,8 @@
import { NgModule } from '@angular/core';
-import { CoreMainMenuDelegate } from '@core/mainmenu/services/delegate';
-import { CoreHomeMainMenuHandler } from './handlers/mainmenu';
-
@NgModule({
imports: [],
declarations: [],
})
-export class CoreCoursesModule {
-
- constructor(mainMenuDelegate: CoreMainMenuDelegate) {
- mainMenuDelegate.registerHandler(new CoreHomeMainMenuHandler());
- }
-
-}
+export class CoreCoursesModule { }
diff --git a/src/app/core/login/pages/site/site.page.ts b/src/app/core/login/pages/site/site.page.ts
index 158594e0d..67aef30cb 100644
--- a/src/app/core/login/pages/site/site.page.ts
+++ b/src/app/core/login/pages/site/site.page.ts
@@ -79,7 +79,7 @@ export class CoreLoginSitePage implements OnInit {
// Load fixed sites if they're set.
if (CoreLoginHelper.instance.hasSeveralFixedSites()) {
url = this.initSiteSelector();
- } else if (CoreConstants.CONFIG.enableonboarding && !CoreApp.instance.isIOS() && !CoreApp.instance.isMac()) {
+ } else if (CoreConstants.CONFIG.enableonboarding && !CoreApp.instance.isIOS()) {
this.initOnboarding();
}
diff --git a/src/app/core/login/services/helper.ts b/src/app/core/login/services/helper.ts
index 5c7d9609b..1d48d43fd 100644
--- a/src/app/core/login/services/helper.ts
+++ b/src/app/core/login/services/helper.ts
@@ -601,11 +601,6 @@ export class CoreLoginHelperProvider {
* @return True if embedded browser, false othwerise.
*/
isSSOEmbeddedBrowser(code: number): boolean {
- if (CoreApp.instance.isLinux()) {
- // In Linux desktop app, always use embedded browser.
- return true;
- }
-
return code == CoreConstants.LOGIN_SSO_INAPP_CODE;
}
@@ -722,16 +717,11 @@ export class CoreLoginHelperProvider {
oauthsso: params.id,
});
- if (CoreApp.instance.isLinux()) {
- // In Linux desktop app, always use embedded browser.
- CoreUtils.instance.openInApp(loginUrl);
- } else {
- // Always open it in browser because the user might have the session stored in there.
- CoreUtils.instance.openInBrowser(loginUrl);
+ // Always open it in browser because the user might have the session stored in there.
+ CoreUtils.instance.openInBrowser(loginUrl);
- const nav = window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
- nav.app?.exitApp();
- }
+ const nav = window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
+ nav.app?.exitApp();
return true;
}
@@ -1071,7 +1061,6 @@ export class CoreLoginHelperProvider {
*/
protected showMoodleAppNoticeModal(message: string): void {
const storesConfig: CoreStoreConfig = CoreConstants.CONFIG.appstores;
- storesConfig.desktop = 'https://download.moodle.org/desktop/';
storesConfig.mobile = 'https://download.moodle.org/mobile/';
storesConfig.default = 'https://download.moodle.org/mobile/';
diff --git a/src/app/core/courses/handlers/mainmenu.ts b/src/app/core/mainmenu/handlers/mainmenu.ts
similarity index 92%
rename from src/app/core/courses/handlers/mainmenu.ts
rename to src/app/core/mainmenu/handlers/mainmenu.ts
index 337ddaed5..a4c2d1fad 100644
--- a/src/app/core/courses/handlers/mainmenu.ts
+++ b/src/app/core/mainmenu/handlers/mainmenu.ts
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '@core/mainmenu/services/delegate';
+import { CoreMainMenuHandler, CoreMainMenuHandlerData } from '../services/delegate';
/**
* Handler to add Home into main menu.
@@ -51,7 +51,7 @@ export class CoreHomeMainMenuHandler implements CoreMainMenuHandler {
getDisplayData(): CoreMainMenuHandlerData {
return {
icon: 'fa-home',
- title: 'core.courses.mymoodle',
+ title: 'core.mainmenu.home',
page: 'home',
class: 'core-home-handler',
};
diff --git a/src/app/core/mainmenu/lang/en.json b/src/app/core/mainmenu/lang/en.json
index 4ff96fbf7..a6558e06e 100644
--- a/src/app/core/mainmenu/lang/en.json
+++ b/src/app/core/mainmenu/lang/en.json
@@ -1,6 +1,7 @@
{
"changesite": "Change site",
"help": "Help",
+ "home": "Home",
"logout": "Log out",
"website": "Website"
-}
\ No newline at end of file
+}
diff --git a/src/app/core/mainmenu/mainmenu-routing.module.ts b/src/app/core/mainmenu/mainmenu-routing.module.ts
index 9633807c5..9e45e3e5e 100644
--- a/src/app/core/mainmenu/mainmenu-routing.module.ts
+++ b/src/app/core/mainmenu/mainmenu-routing.module.ts
@@ -25,7 +25,7 @@ const routes: Routes = [
children: [
{
path: 'home', // @todo: Add this route dynamically.
- loadChildren: () => import('../courses/pages/home/home.page.module').then( m => m.CoreCoursesHomePageModule),
+ loadChildren: () => import('./pages/home/home.page.module').then( m => m.CoreHomePageModule),
},
{
path: 'more',
diff --git a/src/app/core/mainmenu/mainmenu.module.ts b/src/app/core/mainmenu/mainmenu.module.ts
index 1cd8f561e..8e4e5fde5 100644
--- a/src/app/core/mainmenu/mainmenu.module.ts
+++ b/src/app/core/mainmenu/mainmenu.module.ts
@@ -18,12 +18,16 @@ import { CommonModule } from '@angular/common';
import { IonicModule } from '@ionic/angular';
import { TranslateModule } from '@ngx-translate/core';
-import { CoreComponentsModule } from '@/app/components/components.module';
-import { CoreDirectivesModule } from '@/app/directives/directives.module';
+import { CoreComponentsModule } from '@components/components.module';
+import { CoreDirectivesModule } from '@directives/directives.module';
+
+import { CoreMainMenuDelegate } from './services/delegate';
import { CoreMainMenuRoutingModule } from './mainmenu-routing.module';
import { CoreMainMenuPage } from './pages/menu/menu.page';
import { CoreMainMenuMorePage } from './pages/more/more.page';
+import { CoreHomeMainMenuHandler } from './handlers/mainmenu';
+
@NgModule({
imports: [
@@ -39,4 +43,10 @@ import { CoreMainMenuMorePage } from './pages/more/more.page';
CoreMainMenuMorePage,
],
})
-export class CoreMainMenuModule {}
+export class CoreMainMenuModule {
+
+ constructor(mainMenuDelegate: CoreMainMenuDelegate) {
+ mainMenuDelegate.registerHandler(new CoreHomeMainMenuHandler());
+ }
+
+}
diff --git a/src/app/core/courses/pages/home/home.html b/src/app/core/mainmenu/pages/home/home.html
similarity index 79%
rename from src/app/core/courses/pages/home/home.html
rename to src/app/core/mainmenu/pages/home/home.html
index 79b79100d..2b428a553 100644
--- a/src/app/core/courses/pages/home/home.html
+++ b/src/app/core/mainmenu/pages/home/home.html
@@ -16,5 +16,7 @@
- Home page.
-
\ No newline at end of file
+
+ Home page
+
+
diff --git a/src/app/core/courses/pages/home/home.page.module.ts b/src/app/core/mainmenu/pages/home/home.page.module.ts
similarity index 89%
rename from src/app/core/courses/pages/home/home.page.module.ts
rename to src/app/core/mainmenu/pages/home/home.page.module.ts
index 9397ce678..ef2e8f653 100644
--- a/src/app/core/courses/pages/home/home.page.module.ts
+++ b/src/app/core/mainmenu/pages/home/home.page.module.ts
@@ -21,12 +21,12 @@ import { TranslateModule } from '@ngx-translate/core';
import { CoreComponentsModule } from '@components/components.module';
import { CoreDirectivesModule } from '@directives/directives.module';
-import { CoreCoursesHomePage } from './home.page';
+import { CoreHomePage } from './home.page';
const routes: Routes = [
{
path: '',
- component: CoreCoursesHomePage,
+ component: CoreHomePage,
},
];
@@ -40,8 +40,8 @@ const routes: Routes = [
CoreDirectivesModule,
],
declarations: [
- CoreCoursesHomePage,
+ CoreHomePage,
],
exports: [RouterModule],
})
-export class CoreCoursesHomePageModule {}
+export class CoreHomePageModule {}
diff --git a/src/app/core/courses/pages/home/home.page.ts b/src/app/core/mainmenu/pages/home/home.page.ts
similarity index 90%
rename from src/app/core/courses/pages/home/home.page.ts
rename to src/app/core/mainmenu/pages/home/home.page.ts
index 1664c9d14..b5b2410b2 100644
--- a/src/app/core/courses/pages/home/home.page.ts
+++ b/src/app/core/mainmenu/pages/home/home.page.ts
@@ -18,11 +18,11 @@ import { Component, OnInit } from '@angular/core';
* Page that displays the Home.
*/
@Component({
- selector: 'page-core-courses-home',
+ selector: 'page-core-home',
templateUrl: 'home.html',
styleUrls: ['home.scss'],
})
-export class CoreCoursesHomePage implements OnInit {
+export class CoreHomePage implements OnInit {
siteName = 'Hello world';
diff --git a/src/app/core/courses/pages/home/home.scss b/src/app/core/mainmenu/pages/home/home.scss
similarity index 100%
rename from src/app/core/courses/pages/home/home.scss
rename to src/app/core/mainmenu/pages/home/home.scss
diff --git a/src/app/core/mainmenu/pages/more/more.html b/src/app/core/mainmenu/pages/more/more.html
index be3de959f..5edaa06e7 100644
--- a/src/app/core/mainmenu/pages/more/more.html
+++ b/src/app/core/mainmenu/pages/more/more.html
@@ -22,7 +22,7 @@
+ (click)="openHandler(handler)" title="{{ handler.title | translate }}" detail="true" details>
{{ handler.title | translate}}
@@ -32,47 +32,47 @@
-
+
{{ 'core.scanqr' | translate }}
+ title="{{ 'core.mainmenu.website' | translate }}" details>
{{ 'core.mainmenu.website' | translate }}
+ title="{{ 'core.mainmenu.help' | translate }}" details>
{{ 'core.mainmenu.help' | translate }}
-
+
{{ 'core.settings.preferences' | translate }}
-
+
{{ logoutLabel | translate }}
@@ -80,7 +80,7 @@
+ title="{{ 'core.settings.appsettings' | translate }}" details>
{{ 'core.settings.appsettings' | translate }}
diff --git a/src/app/core/settings/pages/about/about.html b/src/app/core/settings/pages/about/about.html
index c0d25bb80..8a47fbf42 100644
--- a/src/app/core/settings/pages/about/about.html
+++ b/src/app/core/settings/pages/about/about.html
@@ -1,4 +1,3 @@
-
@@ -11,18 +10,18 @@
-
+
{{ appName }} {{ versionName }}
-
+
{{ 'core.settings.opensourcelicenses' | translate }}
-
+
{{ 'core.settings.privacypolicy' | translate }}
-
+
{{ 'core.settings.deviceinfo' | translate }}
diff --git a/src/app/core/settings/pages/about/about.page.ts b/src/app/core/settings/pages/about/about.page.ts
index cf00be122..bc35c3244 100644
--- a/src/app/core/settings/pages/about/about.page.ts
+++ b/src/app/core/settings/pages/about/about.page.ts
@@ -33,7 +33,7 @@ export class CoreSettingsAboutPage {
) {
const currentSite = CoreSites.instance.getCurrentSite();
- this.appName = CoreApp.instance.isDesktop() ? CoreConstants.CONFIG.desktopappname : CoreConstants.CONFIG.appname;
+ this.appName = CoreConstants.CONFIG.appname;
this.versionName = CoreConstants.CONFIG.versionname;
// Calculate the privacy policy to use.
diff --git a/src/app/core/settings/pages/deviceinfo/deviceinfo.page.ts b/src/app/core/settings/pages/deviceinfo/deviceinfo.page.ts
index 322fb6585..6149b260b 100644
--- a/src/app/core/settings/pages/deviceinfo/deviceinfo.page.ts
+++ b/src/app/core/settings/pages/deviceinfo/deviceinfo.page.ts
@@ -117,25 +117,14 @@ export class CoreSettingsDeviceInfoPage implements OnDestroy {
}
}
} else {
- this.deviceInfo.deviceType = appProvider.isDesktop() ? 'desktop' : 'browser';
- if (appProvider.isLinux()) {
- this.deviceInfo.deviceOs = 'linux';
- this.deviceOsTranslated = 'Linux';
- } else if (appProvider.isMac()) {
- this.deviceInfo.deviceOs = 'mac';
- this.deviceOsTranslated = 'MacOS';
- } else if (appProvider.isWindows()) {
- this.deviceInfo.deviceOs = 'windows';
- this.deviceOsTranslated = 'Windows';
+ this.deviceInfo.deviceType = 'browser';
+ const matches = navigator.userAgent.match(/\(([^)]*)\)/);
+ if (matches && matches.length > 1) {
+ this.deviceInfo.deviceOs = matches[1];
+ this.deviceOsTranslated = matches[1];
} else {
- const matches = navigator.userAgent.match(/\(([^)]*)\)/);
- if (matches && matches.length > 1) {
- this.deviceInfo.deviceOs = matches[1];
- this.deviceOsTranslated = matches[1];
- } else {
- this.deviceInfo.deviceOs = 'unknown';
- this.deviceOsTranslated = translate.instant('core.unknown');
- }
+ this.deviceInfo.deviceOs = 'unknown';
+ this.deviceOsTranslated = translate.instant('core.unknown');
}
}
diff --git a/src/app/directives/fa-icon.ts b/src/app/directives/fa-icon.ts
index c68c7bdf5..f2f60c509 100644
--- a/src/app/directives/fa-icon.ts
+++ b/src/app/directives/fa-icon.ts
@@ -32,8 +32,6 @@ export class CoreFaIconDirective implements OnChanges {
@Input() name = '';
- // TODO: Support slash, RTL and fixed width.
-
protected element: HTMLElement;
protected logger: CoreLogger;
diff --git a/src/app/lang/en.json b/src/app/lang/en.json
index 00ce91b93..bd3da88ca 100644
--- a/src/app/lang/en.json
+++ b/src/app/lang/en.json
@@ -1,11 +1,18 @@
{
"back": "Back",
"browser": "Browser",
+ "cannotconnect": "Cannot connect",
+ "cannotconnecttrouble": "We're having trouble connecting to your site.",
+ "cannotconnectverify": "Please check the address is correct.",
"copiedtoclipboard": "Text copied to clipboard",
+ "loading": "Loading",
+ "needhelp": "Need help?",
+ "networkerrormsg": "There was a problem connecting to the site. Please check your connection and try again.",
"no": "No",
"offline": "Offline",
"ok": "OK",
"online": "Online",
+ "tryagain": "Try again",
"unknown": "Unknown",
"yes": "Yes"
}
diff --git a/src/app/services/app.ts b/src/app/services/app.ts
index 2862dc336..a22293047 100644
--- a/src/app/services/app.ts
+++ b/src/app/services/app.ts
@@ -226,22 +226,6 @@ export class CoreAppProvider {
* @return Store URL.
*/
getAppStoreUrl(storesConfig: CoreStoreConfig): string | undefined {
- if (this.isMac() && storesConfig.mac) {
- return 'itms-apps://itunes.apple.com/app/' + storesConfig.mac;
- }
-
- if (this.isWindows() && storesConfig.windows) {
- return 'https://www.microsoft.com/p/' + storesConfig.windows;
- }
-
- if (this.isLinux() && storesConfig.linux) {
- return storesConfig.linux;
- }
-
- if (this.isDesktop() && storesConfig.desktop) {
- return storesConfig.desktop;
- }
-
if (this.isIOS() && storesConfig.ios) {
return 'itms-apps://itunes.apple.com/app/' + storesConfig.ios;
}
@@ -260,10 +244,11 @@ export class CoreAppProvider {
/**
* Checks if the app is running in a 64 bits desktop environment (not browser).
*
- * @return Whether the app is running in a 64 bits desktop environment (not browser).
+ * @return false.
+ * @deprecated Desktop support has been removed.
*/
is64Bits(): boolean {
- return this.isDesktop() && window.process.arch == 'x64';
+ return false;
}
/**
@@ -278,10 +263,10 @@ export class CoreAppProvider {
/**
* Checks if the app is running in a desktop environment (not browser).
*
- * @return Whether the app is running in a desktop environment (not browser).
+ * @return false.
+ * @deprecated Desktop support has been removed.
*/
isDesktop(): boolean {
- // @todo
return false;
}
@@ -324,39 +309,21 @@ export class CoreAppProvider {
/**
* Check if the app is running in a Linux environment.
*
- * @return Whether it's running in a Linux environment.
+ * @return false.
+ * @deprecated Desktop support has been removed.
*/
isLinux(): boolean {
- if (!this.isDesktop()) {
- return false;
- }
-
- try {
- // @todo return require('os').platform().indexOf('linux') === 0;
-
- return false;
- } catch (ex) {
- return false;
- }
+ return false;
}
/**
* Check if the app is running in a Mac OS environment.
*
- * @return Whether it's running in a Mac OS environment.
+ * @return false.
+ * @deprecated Desktop support has been removed.
*/
isMac(): boolean {
- if (!this.isDesktop()) {
- return false;
- }
-
- try {
- // @todo return require('os').platform().indexOf('darwin') === 0;
-
- return false;
- } catch (ex) {
- return false;
- }
+ return false;
}
/**
@@ -435,20 +402,11 @@ export class CoreAppProvider {
/**
* Check if the app is running in a Windows environment.
*
- * @return Whether it's running in a Windows environment.
+ * @return false.
+ * @deprecated Desktop support has been removed.
*/
isWindows(): boolean {
- if (!this.isDesktop()) {
- return false;
- }
-
- try {
- // @todo return require('os').platform().indexOf('win') === 0;
-
- return false;
- } catch (ex) {
- return false;
- }
+ return false;
}
/**
@@ -724,26 +682,6 @@ export type CoreRedirectData = {
* Store config data.
*/
export type CoreStoreConfig = {
- /**
- * ID of the Apple store where the desktop Mac app is uploaded.
- */
- mac?: string;
-
- /**
- * ID of the Windows store where the desktop Windows app is uploaded.
- */
- windows?: string;
-
- /**
- * Url with the desktop linux download link.
- */
- linux?: string;
-
- /**
- * Fallback URL when the desktop options is not set.
- */
- desktop?: string;
-
/**
* ID of the Apple store where the mobile iOS app is uploaded.
*/
diff --git a/src/app/services/cron.ts b/src/app/services/cron.ts
index a4e6cdf38..fd13576ab 100644
--- a/src/app/services/cron.ts
+++ b/src/app/services/cron.ts
@@ -35,7 +35,6 @@ export class CoreCronDelegate {
// Constants.
static readonly DEFAULT_INTERVAL = 3600000; // Default interval is 1 hour.
static readonly MIN_INTERVAL = 300000; // Minimum interval is 5 minutes.
- static readonly DESKTOP_MIN_INTERVAL = 60000; // Minimum interval in desktop is 1 minute.
static readonly MAX_TIME_PROCESS = 120000; // Max time a process can block the queue. Defaults to 2 minutes.
// Variables for database.
@@ -237,7 +236,7 @@ export class CoreCronDelegate {
}
// Don't allow intervals lower than the minimum.
- const minInterval = CoreApp.instance.isDesktop() ? CoreCronDelegate.DESKTOP_MIN_INTERVAL : CoreCronDelegate.MIN_INTERVAL;
+ const minInterval = CoreCronDelegate.MIN_INTERVAL;
const handlerInterval = this.handlers[name].getInterval!();
if (!handlerInterval) {
diff --git a/src/app/services/file.ts b/src/app/services/file.ts
index 6d9702625..980bc83d0 100644
--- a/src/app/services/file.ts
+++ b/src/app/services/file.ts
@@ -568,7 +568,7 @@ export class CoreFileProvider {
// Create file (and parent folders) to prevent errors.
const fileEntry = await this.createFile(path);
- if (this.isHTMLAPI && !CoreApp.instance.isDesktop() &&
+ if (this.isHTMLAPI &&
(typeof data == 'string' || data.toString() == '[object ArrayBuffer]')) {
// We need to write Blobs.
const extension = CoreMimetypeUtils.instance.getFileExtension(path);
diff --git a/src/app/services/filepool.ts b/src/app/services/filepool.ts
index f1b2ec9f2..6baddc81c 100644
--- a/src/app/services/filepool.ts
+++ b/src/app/services/filepool.ts
@@ -1756,12 +1756,8 @@ export class CoreFilepoolProvider {
const path = await this.getFilePath(siteId, fileId);
const fileEntry = await CoreFile.instance.getFile(path);
- // This URL is usually used to launch files or put them in HTML. In desktop we need the internal URL.
- if (CoreApp.instance.isDesktop()) {
- return fileEntry.toInternalURL();
- } else {
- return fileEntry.toURL();
- }
+ // This URL is usually used to launch files or put them in HTML.
+ return fileEntry.toURL();
}
/**
@@ -2937,11 +2933,6 @@ export class CoreFilepoolProvider {
return;
}
- if (CoreApp.instance.isDesktop()) {
- // In desktop always download first.
- return;
- }
-
const mimetype = await CoreUtils.instance.getMimeTypeFromUrl(url);
// If the file is streaming (audio or video) we reject.
if (mimetype.indexOf('video') != -1 || mimetype.indexOf('audio') != -1) {
diff --git a/src/app/services/local-notifications.ts b/src/app/services/local-notifications.ts
index 2c38641f7..5f1c7e3d7 100644
--- a/src/app/services/local-notifications.ts
+++ b/src/app/services/local-notifications.ts
@@ -222,8 +222,7 @@ export class CoreLocalNotificationsProvider {
*/
canDisableSound(): boolean {
// Only allow disabling sound in Android 7 or lower. In iOS and Android 8+ it can easily be done with system settings.
- return this.isAvailable() &&!CoreApp.instance.isDesktop() && CoreApp.instance.isAndroid() &&
- Number(Device.instance.version?.split('.')[0]) < 8;
+ return this.isAvailable() && CoreApp.instance.isAndroid() && Number(Device.instance.version?.split('.')[0]) < 8;
}
/**
@@ -363,7 +362,7 @@ export class CoreLocalNotificationsProvider {
isAvailable(): boolean {
const win = window; // eslint-disable-line @typescript-eslint/no-explicit-any
- return CoreApp.instance.isDesktop() || !!win.cordova?.plugins?.notification?.local;
+ return !!win.cordova?.plugins?.notification?.local;
}
/**
diff --git a/src/app/services/sites.ts b/src/app/services/sites.ts
index 9292eacf4..71604d276 100644
--- a/src/app/services/sites.ts
+++ b/src/app/services/sites.ts
@@ -888,7 +888,6 @@ export class CoreSitesProvider {
const storesConfig: CoreStoreConfig = {
android: config.tool_mobile_androidappid,
ios: config.tool_mobile_iosappid,
- desktop: config.tool_mobile_setuplink || 'https://download.moodle.org/desktop/',
mobile: config.tool_mobile_setuplink || 'https://download.moodle.org/mobile/',
default: config.tool_mobile_setuplink,
};
diff --git a/src/app/services/utils/dom.ts b/src/app/services/utils/dom.ts
index 5dfa487d2..86b2ccf07 100644
--- a/src/app/services/utils/dom.ts
+++ b/src/app/services/utils/dom.ts
@@ -13,7 +13,7 @@
// limitations under the License.
import { Injectable, SimpleChange, ElementRef, KeyValueChanges } from '@angular/core';
-import { DomSanitizer, SafeHtml } from '@angular/platform-browser';
+import { DomSanitizer } from '@angular/platform-browser';
import { IonContent } from '@ionic/angular';
import { AlertOptions, AlertButton, TextFieldTypes } from '@ionic/core';
import { Md5 } from 'ts-md5';
@@ -144,11 +144,6 @@ export class CoreDomUtilsProvider {
const readableSize = CoreTextUtils.instance.bytesToSize(size.size, 2);
const getAvailableBytes = async (): Promise => {
- if (CoreApp.instance.isDesktop()) {
- // Free space calculation is not supported on desktop.
- return null;
- }
-
const availableBytes = await CoreFile.instance.calculateFreeSpace();
if (CoreApp.instance.isAndroid()) {
@@ -575,18 +570,6 @@ export class CoreDomUtilsProvider {
return parseInt(style[measure], 10) || 0;
}
- /**
- * Get the HTML code to render a connection warning icon.
- *
- * @return HTML Code.
- */
- getConnectionWarningIconHtml(): string {
- return '' +
- '' +
- '' +
- '
';
- }
-
/**
* Returns width of an element.
*
@@ -655,18 +638,14 @@ export class CoreDomUtilsProvider {
}
/**
- * Given an error message, return a suitable error title.
+ * Given a message, it deduce if it's a network error.
*
- * @param message The error message.
- * @return Title.
+ * @param message Message text.
+ * @return True if the message error is a network error, false otherwise.
*/
- private getErrorTitle(message: string): SafeHtml | string {
- if (message == Translate.instance.instant('core.networkerrormsg') ||
- message == Translate.instance.instant('core.fileuploader.errormustbeonlinetoupload')) {
- return this.domSanitizer.bypassSecurityTrustHtml(this.getConnectionWarningIconHtml());
- }
-
- return CoreTextUtils.instance.decodeHTML(Translate.instance.instant('core.error'));
+ protected isNetworkError(message: string): boolean {
+ return message == Translate.instance.instant('core.networkerrormsg') ||
+ message == Translate.instance.instant('core.fileuploader.errormustbeonlinetoupload');
}
/**
@@ -1245,7 +1224,7 @@ export class CoreDomUtilsProvider {
// Store the alert and remove it when dismissed.
this.displayedAlerts[alertId] = alert;
- // // Set the callbacks to trigger an observable event.
+ // Set the callbacks to trigger an observable event.
// eslint-disable-next-line promise/catch-or-return, promise/always-return
alert.onDidDismiss().then(() => {
delete this.displayedAlerts[alertId];
@@ -1371,7 +1350,18 @@ export class CoreDomUtilsProvider {
return Promise.resolve(null);
}
- return this.showAlert( this.getErrorTitle(message), message, undefined, autocloseTime);
+ const alertOptions: AlertOptions = {
+ message: message,
+ buttons: [Translate.instance.instant('core.ok')],
+ };
+
+ if (this.isNetworkError(message)) {
+ alertOptions.cssClass = 'core-alert-network-error';
+ } else {
+ alertOptions.header = Translate.instance.instant('core.error');
+ }
+
+ return this.showAlertWithOptions(alertOptions, autocloseTime);
}
/**
diff --git a/src/app/services/utils/utils.ts b/src/app/services/utils/utils.ts
index 84f793f3e..e8eedbb87 100644
--- a/src/app/services/utils/utils.ts
+++ b/src/app/services/utils/utils.ts
@@ -227,15 +227,10 @@ export class CoreUtilsProvider {
/**
* Close the InAppBrowser window.
- *
- * @param closeAll Desktop only. True to close all secondary windows, false to close only the "current" one.
*/
- closeInAppBrowser(closeAll?: boolean): void {
+ closeInAppBrowser(): void {
if (this.iabInstance) {
this.iabInstance.close();
- if (closeAll && CoreApp.instance.isDesktop()) {
- // @todo require('electron').ipcRenderer.send('closeSecondaryWindows');
- }
}
}
@@ -959,7 +954,7 @@ export class CoreUtilsProvider {
this.iabInstance = InAppBrowser.instance.create(url, '_blank', options);
- if (CoreApp.instance.isDesktop() || CoreApp.instance.isMobile()) {
+ if (CoreApp.instance.isMobile()) {
let loadStopSubscription;
const loadStartUrls: string[] = [];
@@ -1011,11 +1006,7 @@ export class CoreUtilsProvider {
* @param url The URL to open.
*/
openInBrowser(url: string): void {
- if (CoreApp.instance.isDesktop()) {
- // @todo
- } else {
- window.open(url, '_system');
- }
+ window.open(url, '_system');
}
/**
@@ -1513,7 +1504,7 @@ export class CoreUtilsProvider {
if (!CoreApp.instance.isMobile()) {
- return Promise.reject('QRScanner isn\'t available in desktop apps.');
+ return Promise.reject('QRScanner isn\'t available in browser.');
}
// Ask the user for permission to use the camera.
diff --git a/src/assets/icon/favicon.ico b/src/assets/icon/favicon.ico
deleted file mode 100644
index 483c9647c..000000000
Binary files a/src/assets/icon/favicon.ico and /dev/null differ
diff --git a/src/assets/icon/favicon.png b/src/assets/icon/favicon.png
new file mode 100644
index 000000000..7abfc0a4f
Binary files /dev/null and b/src/assets/icon/favicon.png differ
diff --git a/src/assets/lang/en.json b/src/assets/lang/en.json
index 7eeea14b8..5b7aed812 100644
--- a/src/assets/lang/en.json
+++ b/src/assets/lang/en.json
@@ -302,6 +302,9 @@
"assets.mimetypes.video": "Video file ({{$a.EXT}})",
"core.back": "Back",
"core.browser": "Browser",
+ "core.cannotconnect": "Cannot connect",
+ "core.cannotconnecttrouble": "We're having trouble connecting to your site.",
+ "core.cannotconnectverify": "Please check the address is correct.",
"core.copiedtoclipboard": "Text copied to clipboard",
"core.courses.addtofavourites": "Star this course",
"core.courses.allowguests": "This course allows guest users to enter",
@@ -340,6 +343,7 @@
"core.courses.sendpaymentbutton": "Send payment via PayPal",
"core.courses.show": "Restore to view",
"core.courses.totalcoursesearchresults": "Total courses: {{$a}}",
+ "core.loading": "Loading",
"core.login.auth_email": "Email-based self-registration",
"core.login.authenticating": "Authenticating",
"core.login.cancel": "Cancel",
@@ -464,8 +468,11 @@
"core.login.yourenteredsite": "Connect to your site",
"core.mainmenu.changesite": "Change site",
"core.mainmenu.help": "Help",
+ "core.mainmenu.home": "Home",
"core.mainmenu.logout": "Log out",
"core.mainmenu.website": "Website",
+ "core.needhelp": "Need help?",
+ "core.networkerrormsg": "There was a problem connecting to the site. Please check your connection and try again.",
"core.no": "No",
"core.offline": "Offline",
"core.ok": "OK",
@@ -541,6 +548,7 @@
"core.settings.syncsettings": "Synchronisation settings",
"core.settings.total": "Total",
"core.settings.wificonnection": "Wi-Fi connection",
+ "core.tryagain": "Try again",
"core.unknown": "Unknown",
"core.yes": "Yes"
}
\ No newline at end of file
diff --git a/src/index.html b/src/index.html
index dfdd5afe6..df229b489 100644
--- a/src/index.html
+++ b/src/index.html
@@ -3,7 +3,7 @@
- Ionic App
+ Moodle App
diff --git a/src/theme/app.scss b/src/theme/app.scss
index 033a25fa9..6a8b5c921 100644
--- a/src/theme/app.scss
+++ b/src/theme/app.scss
@@ -1,6 +1,72 @@
-// Add here base app styles.
+// Ionic toolbar.
ion-toolbar ion-back-button,
ion-toolbar .in-toolbar.button-clear {
--color: var(--ion-color-primary-contrast);
}
+
+// Ionic icon.
+ion-icon {
+ &.icon-slash::after,
+ &.icon-backslash::after {
+ content: " ";
+ position: absolute;
+ top: 0;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background-color: var(--ion-color-danger);
+ -webkit-mask: url("/assets/fonts/font-awesome/solid/slash.svg") no-repeat 50% 50%;
+ mask: url("/assets/fonts/font-awesome/solid/slash.svg") no-repeat 50% 50%;
+ }
+
+ &.icon-slash::after {
+ -webkit-transform: scale(-1, 1);
+ transform: scale(-1, 1);
+ }
+
+ &.fa-fw {
+ text-align: center;
+ width: 1.25em;
+ }
+}
+
+[dir=rtl] ion-icon.icon-flip-rtl {
+ -webkit-transform: scale(-1, 1);
+ transform: scale(-1, 1);
+}
+
+// Ionic alert.
+ion-alert.core-alert-network-error .alert-head {
+ position: relative;
+ content: " ";
+ background: url("/assets/fonts/font-awesome/solid/wifi.svg") no-repeat 50% 50%;
+ margin: 25px auto;
+
+ &::after {
+ content: " ";
+ position: absolute;
+ top: -20%;
+ right: -15%;
+ width: 50%;
+ height: 50%;
+ background-color: var(--ion-color-danger);
+ -webkit-mask: url("/assets/fonts/font-awesome/solid/exclamation-triangle.svg") no-repeat 50% 50%;
+ mask: url("/assets/fonts/font-awesome/solid/exclamation-triangle.svg") no-repeat 50% 50%;
+ }
+}
+[dir=rtl] ion-alert.core-alert-network-error .alert-head::after {
+ right: unset;
+ left: -15%;
+}
+
+// Ionic item divider.
+ion-item-divider {
+ --background: var(--gray-lighter);
+ border: 0;
+}
+
+// Ionic list.
+ion-list.list-md {
+ padding-bottom: 0;
+}
diff --git a/src/types/global.d.ts b/src/types/global.d.ts
index 1e05ea6d4..19e8234c4 100644
--- a/src/types/global.d.ts
+++ b/src/types/global.d.ts
@@ -27,7 +27,6 @@ declare global {
CONFIG: {
app_id: string;
appname: string;
- desktopappname: string;
versioncode: number;
versionname: string;
cache_update_frequency_usually: number;