MOBILE-4653 chore: Fix singleton constructors and compiler

main
Pau Ferrer Ocaña 2024-11-11 14:43:09 +01:00
parent 43606fbfb1
commit 0a37db2151
17 changed files with 146 additions and 70 deletions

View File

@ -69,7 +69,7 @@ jobs:
cat circular-dependencies cat circular-dependencies
lines=$(cat circular-dependencies | wc -l) lines=$(cat circular-dependencies | wc -l)
echo "Total circular dependencies: $lines" echo "Total circular dependencies: $lines"
test $lines -eq 130 test $lines -eq 90
- name: JavaScript code compatibility - name: JavaScript code compatibility
run: | run: |
npx check-es-compat www/*.js --polyfills="\{Array,String,TypedArray\}.prototype.at,Object.hasOwn" npx check-es-compat www/*.js --polyfills="\{Array,String,TypedArray\}.prototype.at,Object.hasOwn"

View File

@ -79,23 +79,30 @@ import { Md5 } from 'ts-md5/dist/md5';
// Import core classes that can be useful for site plugins. // Import core classes that can be useful for site plugins.
import { CoreSyncBaseProvider } from '@classes/base-sync'; import { CoreSyncBaseProvider } from '@classes/base-sync';
import { CoreArray } from '@singletons/array'; import { CoreArray } from '@singletons/array';
import { CoreCache } from '@classes/cache';
import { CoreColors } from '@singletons/colors'; import { CoreColors } from '@singletons/colors';
import { CoreCountries } from '@singletons/countries';
import { CoreDelegate } from '@classes/delegate';
import { CoreDirectivesRegistry } from '@singletons/directives-registry'; import { CoreDirectivesRegistry } from '@singletons/directives-registry';
import { CoreDom } from '@singletons/dom'; import { CoreDom } from '@singletons/dom';
import { CoreFileUtils } from '@singletons/file-utils';
import { CoreForms } from '@singletons/form'; import { CoreForms } from '@singletons/form';
import { CoreGeolocationError, CoreGeolocationErrorReason } from '@services/geolocation';
import { CoreKeyboard } from '@singletons/keyboard'; import { CoreKeyboard } from '@singletons/keyboard';
import { CoreMedia } from '@singletons/media';
import { CoreNetwork } from '@services/network';
import { CoreObject } from '@singletons/object'; import { CoreObject } from '@singletons/object';
import { CoreOpener } from '@singletons/opener';
import { CorePath } from '@singletons/path'; import { CorePath } from '@singletons/path';
import { CorePromiseUtils } from '@singletons/promise-utils';
import { CoreSSO } from '@singletons/sso';
import { CoreText } from '@singletons/text'; import { CoreText } from '@singletons/text';
import { CoreTime } from '@singletons/time'; import { CoreTime } from '@singletons/time';
import { CoreUrl } from '@singletons/url'; import { CoreUrl } from '@singletons/url';
import { CoreUtils } from '@singletons/utils';
import { CoreWait } from '@singletons/wait'; import { CoreWait } from '@singletons/wait';
import { CoreWindow } from '@singletons/window'; import { CoreWindow } from '@singletons/window';
import { CoreCache } from '@classes/cache';
import { CoreDelegate } from '@classes/delegate';
import { CoreGeolocationError, CoreGeolocationErrorReason } from '@services/geolocation';
import { getCoreErrorsExportedObjects } from '@classes/errors/errors'; import { getCoreErrorsExportedObjects } from '@classes/errors/errors';
import { CoreNetwork } from '@services/network';
// Import all core modules that define components, directives and pipes. // Import all core modules that define components, directives and pipes.
import { CoreSharedModule } from '@/core/shared.module'; import { CoreSharedModule } from '@/core/shared.module';
@ -312,19 +319,26 @@ export class CoreCompileProvider {
*/ */
instance['Network'] = CoreNetwork.instance; instance['Network'] = CoreNetwork.instance;
instance['CoreNetwork'] = CoreNetwork.instance; instance['CoreNetwork'] = CoreNetwork.instance;
instance['CorePlatform'] = CorePlatform.instance;
instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider;
instance['CoreArray'] = CoreArray; instance['CoreArray'] = CoreArray;
instance['CoreColors'] = CoreColors; instance['CoreColors'] = CoreColors;
instance['CoreCountries'] = CoreCountries;
instance['CoreDirectivesRegistry'] = CoreDirectivesRegistry; instance['CoreDirectivesRegistry'] = CoreDirectivesRegistry;
instance['CoreDom'] = CoreDom; instance['CoreDom'] = CoreDom;
instance['CoreFileUtils'] = CoreFileUtils;
instance['CoreForms'] = CoreForms; instance['CoreForms'] = CoreForms;
instance['CoreKeyboard'] = CoreKeyboard; instance['CoreKeyboard'] = CoreKeyboard;
instance['CoreMedia'] = CoreMedia;
instance['CoreObject'] = CoreObject; instance['CoreObject'] = CoreObject;
instance['CoreOpener'] = CoreOpener;
instance['CorePath'] = CorePath; instance['CorePath'] = CorePath;
instance['CorePlatform'] = CorePlatform.instance;
instance['CorePromiseUtils'] = CorePromiseUtils;
instance['CoreSSO'] = CoreSSO;
instance['CoreSyncBaseProvider'] = CoreSyncBaseProvider;
instance['CoreText'] = CoreText; instance['CoreText'] = CoreText;
instance['CoreTime'] = CoreTime; instance['CoreTime'] = CoreTime;
instance['CoreUrl'] = CoreUrl; instance['CoreUrl'] = CoreUrl;
instance['CoreUtils'] = CoreUtils;
instance['CoreWait'] = CoreWait; instance['CoreWait'] = CoreWait;
instance['CoreWindow'] = CoreWindow; instance['CoreWindow'] = CoreWindow;
instance['CoreCache'] = CoreCache; // @deprecated since 4.4, plugins should use plain objects instead. instance['CoreCache'] = CoreCache; // @deprecated since 4.4, plugins should use plain objects instead.

View File

@ -14,9 +14,16 @@
/** /**
* Helpers to interact with Browser APIs. * Helpers to interact with Browser APIs.
*
* This singleton is not necessary to be exported for site plugins.
*/ */
export class CoreBrowser { export class CoreBrowser {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Check whether the given cookie is set. * Check whether the given cookie is set.
* *
@ -34,9 +41,9 @@ export class CoreBrowser {
* @returns Whether the development setting is set. * @returns Whether the development setting is set.
*/ */
static hasDevelopmentSetting(name: string): boolean { static hasDevelopmentSetting(name: string): boolean {
const setting = this.getDevelopmentSettingKey(name); const setting = CoreBrowser.getDevelopmentSettingKey(name);
return this.hasCookie(setting) || this.hasLocalStorage(setting); return CoreBrowser.hasCookie(setting) || CoreBrowser.hasLocalStorage(setting);
} }
/** /**
@ -84,9 +91,9 @@ export class CoreBrowser {
* @returns Development setting value. * @returns Development setting value.
*/ */
static getDevelopmentSetting(name: string): string | null { static getDevelopmentSetting(name: string): string | null {
const setting = this.getDevelopmentSettingKey(name); const setting = CoreBrowser.getDevelopmentSettingKey(name);
return this.getCookie(setting) ?? this.getLocalStorage(setting); return CoreBrowser.getCookie(setting) ?? CoreBrowser.getLocalStorage(setting);
} }
/** /**
@ -96,7 +103,7 @@ export class CoreBrowser {
* @param value Setting value. * @param value Setting value.
*/ */
static setDevelopmentSetting(name: string, value: string): void { static setDevelopmentSetting(name: string, value: string): void {
const setting = this.getDevelopmentSettingKey(name); const setting = CoreBrowser.getDevelopmentSettingKey(name);
document.cookie = `${setting}=${value};path=/`; document.cookie = `${setting}=${value};path=/`;
localStorage.setItem(setting, value); localStorage.setItem(setting, value);
@ -108,7 +115,7 @@ export class CoreBrowser {
* @param name Setting name. * @param name Setting name.
*/ */
static clearDevelopmentSetting(name: string): void { static clearDevelopmentSetting(name: string): void {
const setting = this.getDevelopmentSettingKey(name); const setting = CoreBrowser.getDevelopmentSettingKey(name);
document.cookie = `${setting}=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT`; document.cookie = `${setting}=;path=/;expires=Thu, 01 Jan 1970 00:00:01 GMT`;
localStorage.removeItem(setting); localStorage.removeItem(setting);

View File

@ -42,6 +42,11 @@ export enum CoreIonicColorNames {
*/ */
export class CoreColors { export class CoreColors {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Returns better contrast color. * Returns better contrast color.
* *
@ -99,7 +104,7 @@ export class CoreColors {
} }
const hex = [0,1,2].map( const hex = [0,1,2].map(
(idx) => this.componentToHex(rgba[idx]), (idx) => CoreColors.componentToHex(rgba[idx]),
).join(''); ).join('');
return '#' + hex; return '#' + hex;

View File

@ -32,9 +32,9 @@ export class CoreDirectivesRegistry {
* @param instance Directive instance. * @param instance Directive instance.
*/ */
static register(element: Element, instance: unknown): void { static register(element: Element, instance: unknown): void {
const list = this.instances.get(element) ?? []; const list = CoreDirectivesRegistry.instances.get(element) ?? [];
list.push(instance); list.push(instance);
this.instances.set(element, list); CoreDirectivesRegistry.instances.set(element, list);
} }
/** /**
@ -45,7 +45,7 @@ export class CoreDirectivesRegistry {
* @returns Directive instance. * @returns Directive instance.
*/ */
static resolve<T>(element?: Element | null, directiveClass?: DirectiveConstructor<T>): T | null { static resolve<T>(element?: Element | null, directiveClass?: DirectiveConstructor<T>): T | null {
const list = (element && this.instances.get(element) as T[]) ?? []; const list = (element && CoreDirectivesRegistry.instances.get(element) as T[]) ?? [];
return list.find(instance => !directiveClass || instance instanceof directiveClass) ?? null; return list.find(instance => !directiveClass || instance instanceof directiveClass) ?? null;
} }
@ -58,7 +58,7 @@ export class CoreDirectivesRegistry {
* @returns Directive instances. * @returns Directive instances.
*/ */
static resolveAll<T>(element?: Element | null, directiveClass?: DirectiveConstructor<T>): T[] { static resolveAll<T>(element?: Element | null, directiveClass?: DirectiveConstructor<T>): T[] {
const list = (element && this.instances.get(element) as T[]) ?? []; const list = (element && CoreDirectivesRegistry.instances.get(element) as T[]) ?? [];
return list.filter(instance => !directiveClass || instance instanceof directiveClass) ?? []; return list.filter(instance => !directiveClass || instance instanceof directiveClass) ?? [];
} }
@ -71,7 +71,7 @@ export class CoreDirectivesRegistry {
* @returns Directive instance. * @returns Directive instance.
*/ */
static require<T>(element: Element, directiveClass?: DirectiveConstructor<T>): T { static require<T>(element: Element, directiveClass?: DirectiveConstructor<T>): T {
const instance = this.resolve(element, directiveClass); const instance = CoreDirectivesRegistry.resolve(element, directiveClass);
if (!instance) { if (!instance) {
throw new Error('Couldn\'t resolve directive instance'); throw new Error('Couldn\'t resolve directive instance');
@ -91,9 +91,9 @@ export class CoreDirectivesRegistry {
element: Element | null, element: Element | null,
directiveClass?: DirectiveConstructor<T>, directiveClass?: DirectiveConstructor<T>,
): Promise<void> { ): Promise<void> {
const instance = this.resolve(element, directiveClass); const instance = CoreDirectivesRegistry.resolve(element, directiveClass);
if (!instance) { if (!instance) {
this.logger.error('No instance registered for element ' + directiveClass, element); CoreDirectivesRegistry.logger.error('No instance registered for element ' + directiveClass, element);
return; return;
} }
@ -129,7 +129,7 @@ export class CoreDirectivesRegistry {
} }
await Promise.all(elements.map(async element => { await Promise.all(elements.map(async element => {
const instances = this.resolveAll<T>(element, directiveClass); const instances = CoreDirectivesRegistry.resolveAll<T>(element, directiveClass);
await Promise.all(instances.map(instance => instance.ready())); await Promise.all(instances.map(instance => instance.ready()));
})); }));
@ -139,7 +139,7 @@ export class CoreDirectivesRegistry {
// Check if there are new elements now that the found elements are ready (there could be nested elements). // Check if there are new elements now that the found elements are ready (there could be nested elements).
if (elements.length !== findElements().length) { if (elements.length !== findElements().length) {
await this.waitDirectivesReady(element, selector, directiveClass); await CoreDirectivesRegistry.waitDirectivesReady(element, selector, directiveClass);
} }
} }
@ -174,7 +174,7 @@ export class CoreDirectivesRegistry {
allElements = allElements.concat(elements); allElements = allElements.concat(elements);
await Promise.all(elements.map(async element => { await Promise.all(elements.map(async element => {
const instances = this.resolveAll<AsyncDirective>(element, directive.class); const instances = CoreDirectivesRegistry.resolveAll<AsyncDirective>(element, directive.class);
await Promise.all(instances.map(instance => instance.ready())); await Promise.all(instances.map(instance => instance.ready()));
})); }));
@ -191,7 +191,7 @@ export class CoreDirectivesRegistry {
}, <Element[]> []); }, <Element[]> []);
if (allElements.length !== elementsAfterReady.length) { if (allElements.length !== elementsAfterReady.length) {
await this.waitMultipleDirectivesReady(element, directives); await CoreDirectivesRegistry.waitMultipleDirectivesReady(element, directives);
} }
} }

View File

@ -512,7 +512,7 @@ export class CoreDom {
return resolve(); return resolve();
} }
unsubscribe = this.watchElementInViewport(element, intersectionRatio, inViewport => { unsubscribe = CoreDom.watchElementInViewport(element, intersectionRatio, inViewport => {
if (!inViewport) { if (!inViewport) {
return; return;
} }
@ -632,7 +632,7 @@ export class CoreDom {
const value = styles.getPropertyValue(property); const value = styles.getPropertyValue(property);
if (property === 'font-size') { if (property === 'font-size') {
if (this.fontSizeZoom === null) { if (CoreDom.fontSizeZoom === null) {
const baseFontSize = 20; const baseFontSize = 20;
const span = document.createElement('span'); const span = document.createElement('span');
span.style.opacity = '0'; span.style.opacity = '0';
@ -640,13 +640,13 @@ export class CoreDom {
document.body.append(span); document.body.append(span);
this.fontSizeZoom = baseFontSize / Number(getComputedStyle(span).fontSize.slice(0, -2)); CoreDom.fontSizeZoom = baseFontSize / Number(getComputedStyle(span).fontSize.slice(0, -2));
span.remove(); span.remove();
} }
if (this.fontSizeZoom !== 1) { if (CoreDom.fontSizeZoom !== 1) {
return `calc(${this.fontSizeZoom} * ${value})`; return `calc(${CoreDom.fontSizeZoom} * ${value})`;
} }
} }

View File

@ -11,24 +11,26 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
import { Injectable } from '@angular/core';
import { makeSingleton } from '@singletons';
/** /**
* Service that stores error logs in memory. * Service that stores error logs in memory.
*/ */
@Injectable({ providedIn: 'root' }) export class CoreErrorLogs {
export class CoreErrorLogsService {
protected errorLogs: CoreSettingsErrorLog[] = []; protected static errorLogs: CoreSettingsErrorLog[] = [];
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Retrieve error logs displayed in the DOM. * Retrieve error logs displayed in the DOM.
* *
* @returns Error logs * @returns Error logs
*/ */
getErrorLogs(): CoreSettingsErrorLog[] { static getErrorLogs(): CoreSettingsErrorLog[] {
return this.errorLogs; return CoreErrorLogs.errorLogs;
} }
/** /**
@ -36,14 +38,12 @@ export class CoreErrorLogsService {
* *
* @param error Error. * @param error Error.
*/ */
addErrorLog(error: CoreSettingsErrorLog): void { static addErrorLog(error: CoreSettingsErrorLog): void {
this.errorLogs.push(error); CoreErrorLogs.errorLogs.push(error);
} }
} }
export const CoreErrorLogs = makeSingleton(CoreErrorLogsService);
export type CoreSettingsErrorLog = { export type CoreSettingsErrorLog = {
data?: unknown; data?: unknown;
message: string; message: string;

View File

@ -122,6 +122,11 @@ export class CoreEvents {
protected static observables: { [eventName: string]: Subject<unknown> } = {}; protected static observables: { [eventName: string]: Subject<unknown> } = {};
protected static uniqueEvents: { [eventName: string]: {data: unknown} } = {}; protected static uniqueEvents: { [eventName: string]: {data: unknown} } = {};
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Listen for a certain event. To stop listening to the event: * Listen for a certain event. To stop listening to the event:
* let observer = eventsProvider.on('something', myCallBack); * let observer = eventsProvider.on('something', myCallBack);
@ -140,8 +145,8 @@ export class CoreEvents {
): CoreEventObserver { ): CoreEventObserver {
// If it's a unique event and has been triggered already, call the callBack. // If it's a unique event and has been triggered already, call the callBack.
// We don't need to create an observer because the event won't be triggered again. // We don't need to create an observer because the event won't be triggered again.
if (this.uniqueEvents[eventName]) { if (CoreEvents.uniqueEvents[eventName]) {
callBack(this.uniqueEvents[eventName].data as CoreEventData<Event, Fallback> & CoreEventSiteData); callBack(CoreEvents.uniqueEvents[eventName].data as CoreEventData<Event, Fallback> & CoreEventSiteData);
// Return a fake observer to prevent errors. // Return a fake observer to prevent errors.
return { return {
@ -151,14 +156,14 @@ export class CoreEvents {
}; };
} }
this.logger.debug(`New observer listening to event '${eventName}'`); CoreEvents.logger.debug(`New observer listening to event '${eventName}'`);
if (this.observables[eventName] === undefined) { if (CoreEvents.observables[eventName] === undefined) {
// No observable for this event, create a new one. // No observable for this event, create a new one.
this.observables[eventName] = new Subject(); CoreEvents.observables[eventName] = new Subject();
} }
const subscription = this.observables[eventName].subscribe( const subscription = CoreEvents.observables[eventName].subscribe(
(value: CoreEventData<Event, Fallback> & CoreEventSiteData) => { (value: CoreEventData<Event, Fallback> & CoreEventSiteData) => {
if (!siteId || value.siteId == siteId) { if (!siteId || value.siteId == siteId) {
callBack(value); callBack(value);
@ -169,7 +174,7 @@ export class CoreEvents {
// Create and return a CoreEventObserver. // Create and return a CoreEventObserver.
return { return {
off: (): void => { off: (): void => {
this.logger.debug(`Stop listening to event '${eventName}'`); CoreEvents.logger.debug(`Stop listening to event '${eventName}'`);
subscription.unsubscribe(); subscription.unsubscribe();
}, },
}; };
@ -211,7 +216,7 @@ export class CoreEvents {
* @returns Observer to stop listening. * @returns Observer to stop listening.
*/ */
static onMultiple<T = unknown>(eventNames: string[], callBack: (value: T) => void, siteId?: string): CoreEventObserver { static onMultiple<T = unknown>(eventNames: string[], callBack: (value: T) => void, siteId?: string): CoreEventObserver {
const observers = eventNames.map((name) => this.on<T>(name, callBack, siteId)); const observers = eventNames.map((name) => CoreEvents.on<T>(name, callBack, siteId));
// Create and return a CoreEventObserver. // Create and return a CoreEventObserver.
return { return {
@ -235,12 +240,12 @@ export class CoreEvents {
data?: CoreEventData<Event, Fallback>, data?: CoreEventData<Event, Fallback>,
siteId?: string, siteId?: string,
): void { ): void {
this.logger.debug(`Event '${eventName}' triggered.`); CoreEvents.logger.debug(`Event '${eventName}' triggered.`);
if (this.observables[eventName]) { if (CoreEvents.observables[eventName]) {
if (siteId) { if (siteId) {
Object.assign(data || {}, { siteId }); Object.assign(data || {}, { siteId });
} }
this.observables[eventName].next(data || {}); CoreEvents.observables[eventName].next(data || {});
} }
} }
@ -256,23 +261,23 @@ export class CoreEvents {
data: CoreEventData<Event, Fallback>, data: CoreEventData<Event, Fallback>,
siteId?: string, siteId?: string,
): void { ): void {
if (this.uniqueEvents[eventName]) { if (CoreEvents.uniqueEvents[eventName]) {
this.logger.debug(`Unique event '${eventName}' ignored because it was already triggered.`); CoreEvents.logger.debug(`Unique event '${eventName}' ignored because it was already triggered.`);
} else { } else {
this.logger.debug(`Unique event '${eventName}' triggered.`); CoreEvents.logger.debug(`Unique event '${eventName}' triggered.`);
if (siteId) { if (siteId) {
Object.assign(data || {}, { siteId }); Object.assign(data || {}, { siteId });
} }
// Store the data so it can be passed to observers that register from now on. // Store the data so it can be passed to observers that register from now on.
this.uniqueEvents[eventName] = { CoreEvents.uniqueEvents[eventName] = {
data, data,
}; };
// Now pass the data to observers. // Now pass the data to observers.
if (this.observables[eventName]) { if (CoreEvents.observables[eventName]) {
this.observables[eventName].next(data); CoreEvents.observables[eventName].next(data);
} }
} }
} }
@ -283,7 +288,7 @@ export class CoreEvents {
* @param eventName Event name. * @param eventName Event name.
*/ */
static waitUntil(eventName: string): Promise<void> { static waitUntil(eventName: string): Promise<void> {
return new Promise(resolve => this.once(eventName, () => resolve())); return new Promise(resolve => CoreEvents.once(eventName, () => resolve()));
} }
} }

View File

@ -22,6 +22,11 @@ export class CoreForms {
private static formIds: Record<string, number> = {}; private static formIds: Record<string, number> = {};
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Get the data from a form. It will only collect elements that have a name. * Get the data from a form. It will only collect elements that have a name.
* *
@ -102,9 +107,9 @@ export class CoreForms {
* @returns Unique id. * @returns Unique id.
*/ */
static uniqueId(name: string): string { static uniqueId(name: string): string {
const count = this.formIds[name] ?? 0; const count = CoreForms.formIds[name] ?? 0;
return `${name}-${this.formIds[name] = count + 1}`; return `${name}-${CoreForms.formIds[name] = count + 1}`;
} }
} }

View File

@ -29,6 +29,11 @@ export class CoreHTMLClasses {
protected static readonly MOODLEAPP_VERSION_PREFIX = 'moodleapp-'; protected static readonly MOODLEAPP_VERSION_PREFIX = 'moodleapp-';
protected static readonly MOODLE_SITE_THEME_PREFIX = 'theme-site-'; protected static readonly MOODLE_SITE_THEME_PREFIX = 'theme-site-';
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Initialize HTML classes. * Initialize HTML classes.
*/ */
@ -101,10 +106,10 @@ export class CoreHTMLClasses {
*/ */
static addSiteClasses(siteInfo: CoreSiteInfo | CoreSiteInfoResponse): void { static addSiteClasses(siteInfo: CoreSiteInfo | CoreSiteInfoResponse): void {
// Add version classes to html tag. // Add version classes to html tag.
this.removeSiteClasses(); CoreHTMLClasses.removeSiteClasses();
this.addVersionClass(CoreHTMLClasses.MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(siteInfo.release || '')); CoreHTMLClasses.addVersionClass(CoreHTMLClasses.MOODLE_VERSION_PREFIX, CoreSites.getReleaseNumber(siteInfo.release || ''));
this.addSiteUrlClass(siteInfo.siteurl); CoreHTMLClasses.addSiteUrlClass(siteInfo.siteurl);
if (siteInfo.theme) { if (siteInfo.theme) {
CoreHTMLClasses.toggleModeClass(CoreHTMLClasses.MOODLE_SITE_THEME_PREFIX + siteInfo.theme, true); CoreHTMLClasses.toggleModeClass(CoreHTMLClasses.MOODLE_SITE_THEME_PREFIX + siteInfo.theme, true);
@ -116,7 +121,7 @@ export class CoreHTMLClasses {
*/ */
static removeSiteClasses(): void { static removeSiteClasses(): void {
// Remove version classes from html tag. // Remove version classes from html tag.
this.removeModeClasses( CoreHTMLClasses.removeModeClasses(
[ [
CoreHTMLClasses.MOODLE_VERSION_PREFIX, CoreHTMLClasses.MOODLE_VERSION_PREFIX,
CoreHTMLClasses.MOODLE_SITE_URL_PREFIX, CoreHTMLClasses.MOODLE_SITE_URL_PREFIX,
@ -161,7 +166,7 @@ export class CoreHTMLClasses {
* Convenience function to add site url to html classes. * Convenience function to add site url to html classes.
*/ */
static addSiteUrlClass(siteUrl: string): void { static addSiteUrlClass(siteUrl: string): void {
const className = this.urlToClassName(siteUrl); const className = CoreHTMLClasses.urlToClassName(siteUrl);
CoreHTMLClasses.toggleModeClass(CoreHTMLClasses.MOODLE_SITE_URL_PREFIX + className, true); CoreHTMLClasses.toggleModeClass(CoreHTMLClasses.MOODLE_SITE_URL_PREFIX + className, true);
} }

View File

@ -28,6 +28,11 @@ export class CoreIcons {
protected static logger = CoreLogger.getInstance('CoreIcons'); protected static logger = CoreLogger.getInstance('CoreIcons');
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Add custom icons to Ionicons. * Add custom icons to Ionicons.
*/ */
@ -47,7 +52,7 @@ export class CoreIcons {
if (CoreIcons.ALIASES[icon]) { if (CoreIcons.ALIASES[icon]) {
if (isAppIcon) { if (isAppIcon) {
this.logger.error(`Icon ${icon} is an alias of ${CoreIcons.ALIASES[icon]}, please use the new name.`); CoreIcons.logger.error(`Icon ${icon} is an alias of ${CoreIcons.ALIASES[icon]}, please use the new name.`);
} }
return { newLibrary, fileName: CoreIcons.ALIASES[icon] }; return { newLibrary, fileName: CoreIcons.ALIASES[icon] };
@ -73,7 +78,7 @@ export class CoreIcons {
CoreIcons.CUSTOM_ICONS[icon] === undefined && CoreIcons.CUSTOM_ICONS[icon] === undefined &&
CoreIcons.CUSTOM_ICONS[CoreIcons.prefixIconName(font, library, icon)] === undefined CoreIcons.CUSTOM_ICONS[CoreIcons.prefixIconName(font, library, icon)] === undefined
) { ) {
this.logger.error(`Icon ${icon} not found`); CoreIcons.logger.error(`Icon ${icon} not found`);
} }
} }

View File

@ -25,6 +25,11 @@ export class CoreKeyboard {
protected static keyboardOpening = false; protected static keyboardOpening = false;
protected static keyboardClosing = false; protected static keyboardClosing = false;
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Closes the keyboard. * Closes the keyboard.
*/ */
@ -51,7 +56,7 @@ export class CoreKeyboard {
*/ */
static onKeyboardShow(keyboardHeight: number): void { static onKeyboardShow(keyboardHeight: number): void {
document.body.classList.add('keyboard-is-open'); document.body.classList.add('keyboard-is-open');
this.setKeyboardShown(true); CoreKeyboard.setKeyboardShown(true);
// Error on iOS calculating size. // Error on iOS calculating size.
// More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 . // More info: https://github.com/ionic-team/ionic-plugin-keyboard/issues/276 .
CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, keyboardHeight); CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, keyboardHeight);
@ -62,7 +67,7 @@ export class CoreKeyboard {
*/ */
static onKeyboardHide(): void { static onKeyboardHide(): void {
document.body.classList.remove('keyboard-is-open'); document.body.classList.remove('keyboard-is-open');
this.setKeyboardShown(false); CoreKeyboard.setKeyboardShown(false);
CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0); CoreEvents.trigger(CoreEvents.KEYBOARD_CHANGE, 0);
} }

View File

@ -17,6 +17,11 @@
*/ */
export class CoreMath { export class CoreMath {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Clamp a value between a minimum and a maximum. * Clamp a value between a minimum and a maximum.
* *

View File

@ -26,6 +26,11 @@ type Subscribable<T> = EventEmitter<T> | Observable<T>;
*/ */
export class CoreSubscriptions { export class CoreSubscriptions {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Listen once to a subscribable object. * Listen once to a subscribable object.
* *

View File

@ -23,6 +23,11 @@ import { SwiperOptions } from 'swiper/types';
*/ */
export class CoreSwiper { export class CoreSwiper {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Initialize a Swiper instance. * Initialize a Swiper instance.
* It will return swiper instance if current is not set or destroyed and new is set and not destroyed. * It will return swiper instance if current is not set or destroyed and new is set and not destroyed.

View File

@ -78,6 +78,11 @@ export class CoreTime {
'13.0': 'Etc/GMT-13', '13.0': 'Etc/GMT-13',
}; };
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Returns years, months, days, hours, minutes and seconds in a human readable format. * Returns years, months, days, hours, minutes and seconds in a human readable format.
* *

View File

@ -20,6 +20,11 @@ import { CorePlatform } from '@services/platform';
*/ */
export class CoreWait { export class CoreWait {
// Avoid creating singleton instances.
private constructor() {
// Nothing to do.
}
/** /**
* Wait until the next tick. * Wait until the next tick.
* *