commit
977eb08a97
|
@ -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 {}
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
<div class="core-empty-box ion-padding" [class.core-empty-box-inline]="(!image && !icon) || inline">
|
||||
<div class="core-empty-box-content">
|
||||
<img *ngIf="image && !icon" [src]="image" role="presentation">
|
||||
<ion-icon *ngIf="icon" [name]="icon" [class.icon-flip-rtl]="flipIconRtl">
|
||||
</ion-icon>
|
||||
<p *ngIf="message" [class.ion-padding-top]="image || icon">{{ message }}</p>
|
||||
<ng-content></ng-content>
|
||||
</div>
|
||||
</div>
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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:
|
||||
* <core-empty-box *ngIf="empty" icon="bell" [message]="'core.emptymessage' | translate"></core-empty-box>
|
||||
*/
|
||||
@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.
|
||||
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 <ion-icon name="fa-icon"> 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();
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<div class="core-loading-container" *ngIf="!hideUntil" role="status"> <!-- @todo [@coreShowHideAnimation] -->
|
||||
<span class="core-loading-spinner">
|
||||
<ion-spinner></ion-spinner>
|
||||
<ion-spinner color="primary"></ion-spinner>
|
||||
<p class="core-loading-message" *ngIf="message" role="status">{{message}}</p>
|
||||
</span>
|
||||
</div>
|
||||
<div #content class="core-loading-content" [id]="uniqueId" [attr.aria-busy]="hideUntil">
|
||||
<ng-content *ngIf="hideUntil">
|
||||
</ng-content> <!-- @todo [@coreShowHideAnimation] -->
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
<ng-content></ng-content>
|
||||
<ion-button icon-only clear [attr.aria-label]="label | translate" [core-suppress-events] (onClick)="toggle($event)">
|
||||
<ion-icon [name]="iconName"></ion-icon>
|
||||
<slot></slot>
|
||||
<ion-button fill="clear" [attr.aria-label]="label | translate" core-suppress-events (onClick)="toggle($event)">
|
||||
<ion-icon [name]="iconName" slot="icon-only"></ion-icon>
|
||||
</ion-button>
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
*
|
||||
* <core-show-password item-content [name]="'password'">
|
||||
* <core-show-password [name]="'password'">
|
||||
* <ion-input type="password" name="password"></ion-input>
|
||||
* </core-show-password>
|
||||
*/
|
||||
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 { }
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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 = <any> window.navigator; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
nav.app?.exitApp();
|
||||
}
|
||||
const nav = <any> 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/';
|
||||
|
||||
|
|
|
@ -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',
|
||||
};
|
|
@ -1,6 +1,7 @@
|
|||
{
|
||||
"changesite": "Change site",
|
||||
"help": "Help",
|
||||
"home": "Home",
|
||||
"logout": "Log out",
|
||||
"website": "Website"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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',
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -16,5 +16,7 @@
|
|||
</ion-header>
|
||||
<ion-content>
|
||||
<!-- @todo -->
|
||||
Home page.
|
||||
</ion-content>
|
||||
<core-empty-box icon="fa-home" [message]="'core.courses.nocourses' | translate">
|
||||
<div>Home page</div>
|
||||
</core-empty-box>
|
||||
</ion-content>
|
|
@ -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 {}
|
|
@ -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';
|
||||
|
|
@ -22,7 +22,7 @@
|
|||
<ion-spinner></ion-spinner>
|
||||
</ion-item>
|
||||
<ion-item button *ngFor="let handler of handlers" [ngClass]="['core-moremenu-handler', handler.class || '']"
|
||||
(click)="openHandler(handler)" title="{{ handler.title | translate }}" detail="true">
|
||||
(click)="openHandler(handler)" title="{{ handler.title | translate }}" detail="true" details>
|
||||
<ion-icon [name]="handler.icon" slot="start"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ handler.title | translate}}</h2>
|
||||
|
@ -32,47 +32,47 @@
|
|||
</ion-item>
|
||||
<ng-container *ngFor="let item of customItems">
|
||||
<ion-item button *ngIf="item.type != 'embedded'" [href]="item.url" title="{{item.label}}" core-link
|
||||
[capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" class="core-moremenu-customitem">
|
||||
[capture]="item.type == 'app'" [inApp]="item.type == 'inappbrowser'" class="core-moremenu-customitem" details>
|
||||
<ion-icon [name]="item.icon" slot="start"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{item.label}}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngIf="item.type == 'embedded'" (click)="openItem(item)" title="{{item.label}}"
|
||||
class="core-moremenu-customitem">
|
||||
class="core-moremenu-customitem" details>
|
||||
<ion-icon [name]="item.icon" slot="start"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{item.label}}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
</ng-container>
|
||||
<ion-item button *ngIf="showScanQR" (click)="scanQR()">
|
||||
<ion-item button *ngIf="showScanQR" (click)="scanQR()" details>
|
||||
<ion-icon name="fa-qrcode" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ 'core.scanqr' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngIf="showWeb && siteInfo" [href]="siteInfo.siteurl" core-link autoLogin="yes"
|
||||
title="{{ 'core.mainmenu.website' | translate }}">
|
||||
title="{{ 'core.mainmenu.website' | translate }}" details>
|
||||
<ion-icon name="globe" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ 'core.mainmenu.website' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button *ngIf="showHelp" [href]="docsUrl" core-link autoLogin="no"
|
||||
title="{{ 'core.mainmenu.help' | translate }}">
|
||||
title="{{ 'core.mainmenu.help' | translate }}" details>
|
||||
<ion-icon name="help-buoy" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ 'core.mainmenu.help' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button (click)="openSitePreferences()" title="{{ 'core.settings.preferences' | translate }}">
|
||||
<ion-item button (click)="openSitePreferences()" title="{{ 'core.settings.preferences' | translate }}" details>
|
||||
<ion-icon name="fa-wrench" slot="start"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.preferences' | translate }}</h2>
|
||||
</ion-label>
|
||||
</ion-item>
|
||||
<ion-item button (click)="logout()" title="{{ logoutLabel | translate }}">
|
||||
<ion-item button (click)="logout()" title="{{ logoutLabel | translate }}" details>
|
||||
<ion-icon name="log-out" slot="start" aria-hidden="true"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ logoutLabel | translate }}</h2>
|
||||
|
@ -80,7 +80,7 @@
|
|||
</ion-item>
|
||||
<ion-item-divider></ion-item-divider>
|
||||
<ion-item button router-direction="forward" routerLink="/settings/app"
|
||||
title="{{ 'core.settings.appsettings' | translate }}">
|
||||
title="{{ 'core.settings.appsettings' | translate }}" details>
|
||||
<ion-icon name="fa-cogs" slot="start"></ion-icon>
|
||||
<ion-label>
|
||||
<h2>{{ 'core.settings.appsettings' | translate }}</h2>
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
<ion-header>
|
||||
<ion-toolbar>
|
||||
<ion-buttons slot="start">
|
||||
|
@ -11,18 +10,18 @@
|
|||
</ion-header>
|
||||
|
||||
<ion-content>
|
||||
<ion-item text-wrap>
|
||||
<ion-item class="ion-text-wrap">
|
||||
<ion-label><h2>{{ appName }} {{ versionName }}</h2></ion-label>
|
||||
</ion-item>
|
||||
<ion-item text-wrap (click)="openPage('licenses')" detail>
|
||||
<ion-item button class="ion-text-wrap" (click)="openPage('licenses')" detail>
|
||||
<ion-icon name="far-copyright" slot="start"></ion-icon>
|
||||
<ion-label>{{ 'core.settings.opensourcelicenses' | translate }}</ion-label>
|
||||
</ion-item>
|
||||
<ion-item text-wrap *ngIf="privacyPolicy" [href]="privacyPolicy" core-link auto-login="no" detail>
|
||||
<ion-item button class="ion-text-wrap" *ngIf="privacyPolicy" [href]="privacyPolicy" core-link auto-login="no" detail>
|
||||
<ion-icon name="fa-user-shield" slot="start"></ion-icon>
|
||||
<ion-label>{{ 'core.settings.privacypolicy' | translate }}</ion-label>
|
||||
</ion-item>
|
||||
<ion-item text-wrap (click)="openPage('deviceinfo')" detail>
|
||||
<ion-item button class="ion-text-wrap" (click)="openPage('deviceinfo')" detail>
|
||||
<ion-icon name="fa-mobile" slot="start"></ion-icon>
|
||||
<ion-label>{{ 'core.settings.deviceinfo' | translate }}</ion-label>
|
||||
</ion-item>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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');
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -32,8 +32,6 @@ export class CoreFaIconDirective implements OnChanges {
|
|||
|
||||
@Input() name = '';
|
||||
|
||||
// TODO: Support slash, RTL and fixed width.
|
||||
|
||||
protected element: HTMLElement;
|
||||
|
||||
protected logger: CoreLogger;
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
{
|
||||
"back": "Back",
|
||||
"browser": "Browser",
|
||||
"cannotconnect": "Cannot connect",
|
||||
"cannotconnecttrouble": "We're having trouble connecting to your site.",
|
||||
"cannotconnectverify": "<strong>Please check the address is correct.</strong>",
|
||||
"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"
|
||||
}
|
||||
|
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 = <any> window; // eslint-disable-line @typescript-eslint/no-explicit-any
|
||||
|
||||
return CoreApp.instance.isDesktop() || !!win.cordova?.plugins?.notification?.local;
|
||||
return !!win.cordova?.plugins?.notification?.local;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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<number | null> => {
|
||||
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 '<div text-center><span class="core-icon-with-badge">' +
|
||||
'<ion-icon role="img" class="icon fa fa-wifi" aria-label="wifi"></ion-icon>' +
|
||||
'<ion-icon class="icon fa fa-exclamation-triangle core-icon-badge"></ion-icon>' +
|
||||
'</span></div>';
|
||||
}
|
||||
|
||||
/**
|
||||
* 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(<string> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 103 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -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": "<strong>Please check the address is correct.</strong>",
|
||||
"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"
|
||||
}
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<title>Ionic App</title>
|
||||
<title>Moodle App</title>
|
||||
|
||||
<base href="/" />
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -27,7 +27,6 @@ declare global {
|
|||
CONFIG: {
|
||||
app_id: string;
|
||||
appname: string;
|
||||
desktopappname: string;
|
||||
versioncode: number;
|
||||
versionname: string;
|
||||
cache_update_frequency_usually: number;
|
||||
|
|
Loading…
Reference in New Issue