Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mobile 3947 #3865

Merged
merged 4 commits into from
Nov 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion scripts/build-behat-plugin.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

const minimatch = require('minimatch');
const { minimatch } = require('minimatch');
const { existsSync, readFileSync, writeFileSync, statSync, renameSync, rmSync } = require('fs');
const { readdir } = require('fs').promises;
const { mkdirSync, copySync } = require('fs-extra');
Expand Down
9 changes: 2 additions & 7 deletions src/addons/filter/displayh5p/services/handlers/displayh5p.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { Injectable, ViewContainerRef, ComponentFactoryResolver } from '@angular/core';
import { Injectable, ViewContainerRef } from '@angular/core';

import { CoreFilterDefaultHandler } from '@features/filter/services/handlers/default-filter';
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@features/filter/services/filter';
Expand All @@ -32,10 +32,6 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle

protected template = document.createElement('template'); // A template element to convert HTML to element.

constructor(protected factoryResolver: ComponentFactoryResolver) {
super();
}

/**
* @inheritdoc
*/
Expand Down Expand Up @@ -95,8 +91,7 @@ export class AddonFilterDisplayH5PHandlerService extends CoreFilterDefaultHandle
const url = placeholder.getAttribute('data-player-src') || '';

// Create the component to display the player.
const factory = this.factoryResolver.resolveComponentFactory(CoreH5PPlayerComponent);
const componentRef = viewContainerRef.createComponent<CoreH5PPlayerComponent>(factory);
const componentRef = viewContainerRef.createComponent<CoreH5PPlayerComponent>(CoreH5PPlayerComponent);

componentRef.instance.src = url;
componentRef.instance.component = component;
Expand Down
6 changes: 2 additions & 4 deletions src/app/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

import { APP_INITIALIZER, COMPILER_OPTIONS, NgModule } from '@angular/core';
import { APP_INITIALIZER, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { RouteReuseStrategy } from '@angular/router';
Expand All @@ -28,7 +28,7 @@ import { AddonsModule } from '@addons/addons.module';

import { AppComponent } from './app.component';
import { AppRoutingModule } from './app-routing.module';
import { JitCompilerFactory } from '@angular/platform-browser-dynamic';

import { CoreCronDelegate } from '@services/cron';
import { CoreSiteInfoCronHandler } from '@services/handlers/site-info-cron';
import { moodleTransitionAnimation } from '@classes/page-transition';
Expand Down Expand Up @@ -71,8 +71,6 @@ export function createTranslateLoader(http: HttpClient): TranslateHttpLoader {
],
providers: [
{ provide: RouteReuseStrategy, useClass: IonicRouteStrategy },
{ provide: COMPILER_OPTIONS, useValue: {}, multi: true },
{ provide: JitCompilerFactory, useClass: JitCompilerFactory, deps: [COMPILER_OPTIONS] },
{
provide: APP_INITIALIZER,
multi: true,
Expand Down
12 changes: 5 additions & 7 deletions src/core/components/dynamic-component/dynamic-component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
OnChanges,
DoCheck,
ViewContainerRef,
ComponentFactoryResolver,
ComponentRef,
KeyValueDiffers,
SimpleChange,
Expand Down Expand Up @@ -70,7 +69,8 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
@Input() data?: Record<string | number, unknown>;

// Get the container where to put the dynamic component.
@ViewChild('dynamicComponent', { read: ViewContainerRef }) set dynamicComponent(el: ViewContainerRef) {
@ViewChild('dynamicComponent', { read: ViewContainerRef })
set dynamicComponent(el: ViewContainerRef) {
this.container = el;

// Use a timeout to avoid ExpressionChangedAfterItHasBeenCheckedError.
Expand All @@ -85,7 +85,6 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
protected lastComponent?: Type<unknown>;

constructor(
protected factoryResolver: ComponentFactoryResolver,
differs: KeyValueDiffers,
protected cdr: ChangeDetectorRef,
protected element: ElementRef,
Expand All @@ -96,7 +95,7 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
}

/**
* Detect changes on input properties.
* @inheritdoc
*/
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
if (changes.component && !this.component) {
Expand All @@ -110,7 +109,7 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
}

/**
* Detect and act upon changes that Angular can’t or won’t detect on its own (objects and arrays).
* @inheritdoc
*/
ngDoCheck(): void {
if (this.instance) {
Expand Down Expand Up @@ -172,8 +171,7 @@ export class CoreDynamicComponent<ComponentClass> implements OnChanges, DoCheck
} else {
try {
// Create the component and add it to the container.
const factory = this.factoryResolver.resolveComponentFactory(this.component);
const componentRef = this.container.createComponent(factory);
const componentRef = this.container.createComponent(this.component);

this.instance = componentRef.instance;
} catch (ex) {
Expand Down
6 changes: 2 additions & 4 deletions src/core/components/navbar-buttons/navbar-buttons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import {
ElementRef,
ViewContainerRef,
ViewChild,
ComponentFactoryResolver,
} from '@angular/core';
import { CoreLogger } from '@singletons/logger';
import { CoreDomUtils } from '@services/utils/dom';
Expand Down Expand Up @@ -78,7 +77,7 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
protected mergedContextMenu?: CoreContextMenuComponent;
protected createdMainContextMenuElement?: HTMLElement;

constructor(element: ElementRef, protected factoryResolver: ComponentFactoryResolver) {
constructor(element: ElementRef) {
this.element = element.nativeElement;
this.logger = CoreLogger.getInstance('CoreNavBarButtonsComponent');

Expand Down Expand Up @@ -186,8 +185,7 @@ export class CoreNavBarButtonsComponent implements OnInit, OnDestroy {
* @returns Created component.
*/
protected createMainContextMenu(): CoreContextMenuComponent {
const factory = this.factoryResolver.resolveComponentFactory(CoreContextMenuComponent);
const componentRef = this.container.createComponent<CoreContextMenuComponent>(factory);
const componentRef = this.container.createComponent(CoreContextMenuComponent);

this.createdMainContextMenuElement = componentRef.location.nativeElement;

Expand Down
42 changes: 24 additions & 18 deletions src/core/features/compile/components/compile-html/compile-html.ts
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import { CoreUtils } from '@services/utils/utils';
*/
@Component({
selector: 'core-compile-html',
template: '<core-loading [hideUntil]="loaded"><ng-container #dynamicComponent></ng-container></core-loading>',
template: '<core-loading [hideUntil]="loaded"><ng-container #dynamicComponent /></core-loading>',
styles: [':host { display: contents; }'],
})
export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
Expand All @@ -66,16 +66,16 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
@Input() jsData?: Record<string, unknown>; // Data to pass to the fake component.
@Input() extraImports: unknown[] = []; // Extra import modules.
@Input() extraProviders: Type<unknown>[] = []; // Extra providers.
@Input() forceCompile?: boolean; // Set it to true to force compile even if the text/javascript hasn't changed.
@Input() forceCompile = false; // Set it to true to force compile even if the text/javascript hasn't changed.
@Output() created = new EventEmitter<unknown>(); // Will emit an event when the component is instantiated.
@Output() compiling = new EventEmitter<boolean>(); // Event that indicates whether the template is being compiled.

loaded = false;
componentInstance?: any; // eslint-disable-line @typescript-eslint/no-explicit-any

// Get the container where to put the content.
@ViewChild('dynamicComponent', { read: ViewContainerRef }) container?: ViewContainerRef;

loaded?: boolean;
componentInstance?: any; // eslint-disable-line @typescript-eslint/no-explicit-any

protected componentRef?: ComponentRef<unknown>;
protected element: HTMLElement;
protected differ: KeyValueDiffer<unknown, unknown>; // To detect changes in the jsData input.
Expand Down Expand Up @@ -114,6 +114,10 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
* @inheritdoc
*/
async ngOnChanges(changes: Record<string, SimpleChange>): Promise<void> {
if (!this.container) {
return;
}

// Only compile if text/javascript has changed or the forceCompile flag has been set to true.
if (this.text !== undefined && (changes.text || changes.javascript ||
(changes.forceCompile && CoreUtils.isTrueOrOne(this.forceCompile)))) {
Expand All @@ -124,16 +128,18 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {

try {
const componentClass = await this.getComponentClass();
const factory = await CoreCompile.createAndCompileComponent(this.text, componentClass, this.extraImports);

// Destroy previous components.
this.componentRef?.destroy();

if (factory) {
// Create the component.
this.componentRef = this.container?.createComponent(factory);
this.componentRef && this.created.emit(this.componentRef.instance);
}
// Create the component.
this.componentRef = await CoreCompile.createAndCompileComponent(
this.text,
componentClass,
this.container,
this.extraImports,
);
this.componentRef && this.created.emit(this.componentRef.instance);

this.loaded = true;
} catch (error) {
Expand Down Expand Up @@ -192,7 +198,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
}

/**
* Component being initialized.
* @inheritdoc
*/
ngOnInit(): void {
// If there is some javascript to run, do it now.
Expand All @@ -204,7 +210,7 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
for (const name in compileInstance.pendingCalls) {
const pendingCall = compileInstance.pendingCalls[name];

if (typeof this[name] == 'function') {
if (typeof this[name] === 'function') {
// Call the function.
Promise.resolve(this[name].apply(this, pendingCall.params)).then(pendingCall.defer.resolve)
.catch(pendingCall.defer.reject);
Expand All @@ -218,21 +224,21 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
}

/**
* Content has been initialized.
* @inheritdoc
*/
ngAfterContentInit(): void {
this.callLifecycleHookOverride('ngAfterContentInit');
}

/**
* View has been initialized.
* @inheritdoc
*/
ngAfterViewInit(): void {
this.callLifecycleHookOverride('ngAfterViewInit');
}

/**
* Component destroyed.
* @inheritdoc
*/
ngOnDestroy(): void {
this.callLifecycleHookOverride('ngOnDestroy');
Expand Down Expand Up @@ -283,9 +289,9 @@ export class CoreCompileHtmlComponent implements OnChanges, OnDestroy, DoCheck {
* once the component has been created.
* @returns Result of the call. Undefined if no component instance or the function doesn't exist.
*/
callComponentFunction(name: string, params?: unknown[], callWhenCreated: boolean = true): unknown {
callComponentFunction(name: string, params?: unknown[], callWhenCreated = true): unknown {
if (this.componentInstance) {
if (typeof this.componentInstance[name] == 'function') {
if (typeof this.componentInstance[name] === 'function') {
return this.componentInstance[name].apply(this.componentInstance, params);
}
} else if (callWhenCreated) {
Expand Down
28 changes: 28 additions & 0 deletions src/core/features/compile/pipes/translate.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// (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 { Injectable, Pipe } from '@angular/core';
import { TranslatePipe } from '@ngx-translate/core';

/**
* Copy of translate pipe to use when compiling a dynamic component.
* For some reason, when compiling a dynamic component the original translate pipe isn't found so we use this copy instead.
*/
@Injectable()
@Pipe({
name: 'translate',
pure: false, // required to update the value when the promise is resolved
standalone: true,
})
export class TranslatePipeForCompile extends TranslatePipe {}
dpalou marked this conversation as resolved.
Show resolved Hide resolved
Loading
Loading