forked from EVOgeek/Vmeda.Online
		
	MOBILE-3565 core: Migrate some core classes
This commit is contained in:
		
							parent
							
								
									1e979b57bb
								
							
						
					
					
						commit
						811bb39781
					
				
							
								
								
									
										352
									
								
								src/app/classes/delegate.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										352
									
								
								src/app/classes/delegate.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,352 @@ | ||||
| // (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 { CoreSites } from '@services/sites'; | ||||
| import { CoreEvents, CoreEventsProvider } from '@services/events'; | ||||
| import { CoreSite } from '@classes/site'; | ||||
| import { CoreLogger } from '@singletons/logger'; | ||||
| 
 | ||||
| /** | ||||
|  * Superclass to help creating delegates | ||||
|  */ | ||||
| export class CoreDelegate { | ||||
| 
 | ||||
|     /** | ||||
|      * Logger instance. | ||||
|      */ | ||||
|     protected logger: CoreLogger; | ||||
| 
 | ||||
|     /** | ||||
|      * List of registered handlers. | ||||
|      */ | ||||
|     protected handlers: { [s: string]: CoreDelegateHandler } = {}; | ||||
| 
 | ||||
|     /** | ||||
|      * List of registered handlers enabled for the current site. | ||||
|      */ | ||||
|     protected enabledHandlers: { [s: string]: CoreDelegateHandler } = {}; | ||||
| 
 | ||||
|     /** | ||||
|      * Default handler | ||||
|      */ | ||||
|     protected defaultHandler: CoreDelegateHandler; | ||||
| 
 | ||||
|     /** | ||||
|      * Time when last updateHandler functions started. | ||||
|      */ | ||||
|     protected lastUpdateHandlersStart: number; | ||||
| 
 | ||||
|     /** | ||||
|      * Feature prefix to check is feature is enabled or disabled in site. | ||||
|      * This check is only made if not false. Override on the subclass or override isFeatureDisabled function. | ||||
|      */ | ||||
|     protected featurePrefix: string; | ||||
| 
 | ||||
|     /** | ||||
|      * Name of the property to be used to index the handlers. By default, the handler's name will be used. | ||||
|      * If your delegate uses a Moodle component name to identify the handlers, please override this property. | ||||
|      * E.g. CoreCourseModuleDelegate uses 'modName' to index the handlers. | ||||
|      */ | ||||
|     protected handlerNameProperty = 'name'; | ||||
| 
 | ||||
|     /** | ||||
|      * Set of promises to update a handler, to prevent doing the same operation twice. | ||||
|      */ | ||||
|     protected updatePromises: {[siteId: string]: {[name: string]: Promise<any>}} = {}; | ||||
| 
 | ||||
|     /** | ||||
|      * Whether handlers have been initialized. | ||||
|      */ | ||||
|     protected handlersInitialized = false; | ||||
| 
 | ||||
|     /** | ||||
|      * Promise to wait for handlers to be initialized. | ||||
|      */ | ||||
|     protected handlersInitPromise: Promise<any>; | ||||
| 
 | ||||
|     /** | ||||
|      * Function to resolve the handlers init promise. | ||||
|      */ | ||||
|     protected handlersInitResolve: (value?: any) => void; | ||||
| 
 | ||||
|     /** | ||||
|      * Constructor of the Delegate. | ||||
|      * | ||||
|      * @param delegateName Delegate name used for logging purposes. | ||||
|      * @param listenSiteEvents Whether to update the handler when a site event occurs (login, site updated, ...). | ||||
|      */ | ||||
|     constructor(delegateName: string, listenSiteEvents?: boolean) { | ||||
|         this.logger = CoreLogger.getInstance(delegateName); | ||||
| 
 | ||||
|         this.handlersInitPromise = new Promise((resolve): void => { | ||||
|             this.handlersInitResolve = resolve; | ||||
|         }); | ||||
| 
 | ||||
|         if (listenSiteEvents) { | ||||
|             // Update handlers on this cases.
 | ||||
|             CoreEvents.instance.on(CoreEventsProvider.LOGIN, this.updateHandlers.bind(this)); | ||||
|             CoreEvents.instance.on(CoreEventsProvider.SITE_UPDATED, this.updateHandlers.bind(this)); | ||||
|             CoreEvents.instance.on(CoreEventsProvider.SITE_PLUGINS_LOADED, this.updateHandlers.bind(this)); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Execute a certain function in a enabled handler. | ||||
|      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||
|      * | ||||
|      * @param handlerName The handler name. | ||||
|      * @param fnName Name of the function to execute. | ||||
|      * @param params Parameters to pass to the function. | ||||
|      * @return Function returned value or default value. | ||||
|      */ | ||||
|     protected executeFunctionOnEnabled(handlerName: string, fnName: string, params?: any[]): any { | ||||
|         return this.execute(this.enabledHandlers[handlerName], fnName, params); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Execute a certain function in a handler. | ||||
|      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||
|      * | ||||
|      * @param handlerName The handler name. | ||||
|      * @param fnName Name of the function to execute. | ||||
|      * @param params Parameters to pass to the function. | ||||
|      * @return Function returned value or default value. | ||||
|      */ | ||||
|     protected executeFunction(handlerName: string, fnName: string, params?: any[]): any { | ||||
|         return this.execute(this.handlers[handlerName], fnName, params); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Execute a certain function in a handler. | ||||
|      * If the handler isn't found or function isn't defined, call the same function in the default handler. | ||||
|      * | ||||
|      * @param handler The handler. | ||||
|      * @param fnName Name of the function to execute. | ||||
|      * @param params Parameters to pass to the function. | ||||
|      * @return Function returned value or default value. | ||||
|      */ | ||||
|     private execute(handler: any, fnName: string, params?: any[]): any { | ||||
|         if (handler && handler[fnName]) { | ||||
|             return handler[fnName].apply(handler, params); | ||||
|         } else if (this.defaultHandler && this.defaultHandler[fnName]) { | ||||
|             return this.defaultHandler[fnName].apply(this.defaultHandler, params); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a handler. | ||||
|      * | ||||
|      * @param handlerName The handler name. | ||||
|      * @param enabled Only enabled, or any. | ||||
|      * @return Handler. | ||||
|      */ | ||||
|     protected getHandler(handlerName: string, enabled: boolean = false): CoreDelegateHandler { | ||||
|         return enabled ? this.enabledHandlers[handlerName] : this.handlers[handlerName]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets the handler full name for a given name. This is useful when the handlerNameProperty is different than "name". | ||||
|      * E.g. blocks are indexed by blockName. If you call this function passing the blockName it will return the name. | ||||
|      * | ||||
|      * @param name Name used to indentify the handler. | ||||
|      * @return Full name of corresponding handler. | ||||
|      */ | ||||
|     getHandlerName(name: string): string { | ||||
|         const handler = this.getHandler(name, true); | ||||
| 
 | ||||
|         if (!handler) { | ||||
|             return ''; | ||||
|         } | ||||
| 
 | ||||
|         return handler.name; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if function exists on a handler. | ||||
|      * | ||||
|      * @param handlerName The handler name. | ||||
|      * @param fnName Name of the function to execute. | ||||
|      * @param onlyEnabled If check only enabled handlers or all. | ||||
|      * @return Function returned value or default value. | ||||
|      */ | ||||
|     protected hasFunction(handlerName: string, fnName: string, onlyEnabled: boolean = true): any { | ||||
|         const handler = onlyEnabled ? this.enabledHandlers[handlerName] : this.handlers[handlerName]; | ||||
| 
 | ||||
|         return handler && handler[fnName]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a handler name has a registered handler (not necessarily enabled). | ||||
|      * | ||||
|      * @param name The handler name. | ||||
|      * @param enabled Only enabled, or any. | ||||
|      * @return If the handler is registered or not. | ||||
|      */ | ||||
|     hasHandler(name: string, enabled: boolean = false): boolean { | ||||
|         return enabled ? typeof this.enabledHandlers[name] !== 'undefined' : typeof this.handlers[name] !== 'undefined'; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a time belongs to the last update handlers call. | ||||
|      * This is to handle the cases where updateHandlers don't finish in the same order as they're called. | ||||
|      * | ||||
|      * @param time Time to check. | ||||
|      * @return Whether it's the last call. | ||||
|      */ | ||||
|     isLastUpdateCall(time: number): boolean { | ||||
|         if (!this.lastUpdateHandlersStart) { | ||||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         return time == this.lastUpdateHandlersStart; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Register a handler. | ||||
|      * | ||||
|      * @param handler The handler delegate object to register. | ||||
|      * @return True when registered, false if already registered. | ||||
|      */ | ||||
|     registerHandler(handler: CoreDelegateHandler): boolean { | ||||
|         const key = handler[this.handlerNameProperty] || handler.name; | ||||
| 
 | ||||
|         if (typeof this.handlers[key] !== 'undefined') { | ||||
|             this.logger.log(`Handler '${handler[this.handlerNameProperty]}' already registered`); | ||||
| 
 | ||||
|             return false; | ||||
|         } | ||||
| 
 | ||||
|         this.logger.log(`Registered handler '${handler[this.handlerNameProperty]}'`); | ||||
|         this.handlers[key] = handler; | ||||
| 
 | ||||
|         return true; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Update the handler for the current site. | ||||
|      * | ||||
|      * @param handler The handler to check. | ||||
|      * @param time Time this update process started. | ||||
|      * @return Resolved when done. | ||||
|      */ | ||||
|     protected updateHandler(handler: CoreDelegateHandler, time: number): Promise<void> { | ||||
|         const siteId = CoreSites.instance.getCurrentSiteId(); | ||||
|         const currentSite = CoreSites.instance.getCurrentSite(); | ||||
|         let promise; | ||||
| 
 | ||||
|         if (this.updatePromises[siteId] && this.updatePromises[siteId][handler.name]) { | ||||
|             // There's already an update ongoing for this handler, return the promise.
 | ||||
|             return this.updatePromises[siteId][handler.name]; | ||||
|         } else if (!this.updatePromises[siteId]) { | ||||
|             this.updatePromises[siteId] = {}; | ||||
|         } | ||||
| 
 | ||||
|         if (!CoreSites.instance.isLoggedIn()) { | ||||
|             promise = Promise.reject(null); | ||||
|         } else if (this.isFeatureDisabled(handler, currentSite)) { | ||||
|             promise = Promise.resolve(false); | ||||
|         } else { | ||||
|             promise = Promise.resolve(handler.isEnabled()); | ||||
|         } | ||||
| 
 | ||||
|         // Checks if the handler is enabled.
 | ||||
|         this.updatePromises[siteId][handler.name] = promise.catch(() => { | ||||
|             return false; | ||||
|         }).then((enabled: boolean) => { | ||||
|             // Check that site hasn't changed since the check started.
 | ||||
|             if (CoreSites.instance.getCurrentSiteId() === siteId) { | ||||
|                 const key = handler[this.handlerNameProperty] || handler.name; | ||||
| 
 | ||||
|                 if (enabled) { | ||||
|                     this.enabledHandlers[key] = handler; | ||||
|                 } else { | ||||
|                     delete this.enabledHandlers[key]; | ||||
|                 } | ||||
|             } | ||||
|         }).finally(() => { | ||||
|             // Update finished, delete the promise.
 | ||||
|             delete this.updatePromises[siteId][handler.name]; | ||||
|         }); | ||||
| 
 | ||||
|         return this.updatePromises[siteId][handler.name]; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if feature is enabled or disabled in the site, depending on the feature prefix and the handler name. | ||||
|      * | ||||
|      * @param handler Handler to check. | ||||
|      * @param site Site to check. | ||||
|      * @return Whether is enabled or disabled in site. | ||||
|      */ | ||||
|     protected isFeatureDisabled(handler: CoreDelegateHandler, site: CoreSite): boolean { | ||||
|         return typeof this.featurePrefix != 'undefined' && site.isFeatureDisabled(this.featurePrefix + handler.name); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Update the handlers for the current site. | ||||
|      * | ||||
|      * @return Resolved when done. | ||||
|      */ | ||||
|     protected updateHandlers(): Promise<void> { | ||||
|         const promises = [], | ||||
|             now = Date.now(); | ||||
| 
 | ||||
|         this.logger.debug('Updating handlers for current site.'); | ||||
| 
 | ||||
|         this.lastUpdateHandlersStart = now; | ||||
| 
 | ||||
|         // Loop over all the handlers.
 | ||||
|         for (const name in this.handlers) { | ||||
|             promises.push(this.updateHandler(this.handlers[name], now)); | ||||
|         } | ||||
| 
 | ||||
|         return Promise.all(promises).then(() => { | ||||
|             return true; | ||||
|         }, () => { | ||||
|             // Never reject.
 | ||||
|             return true; | ||||
|         }).then(() => { | ||||
| 
 | ||||
|             // Verify that this call is the last one that was started.
 | ||||
|             if (this.isLastUpdateCall(now)) { | ||||
|                 this.handlersInitialized = true; | ||||
|                 this.handlersInitResolve(); | ||||
| 
 | ||||
|                 this.updateData(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Update handlers Data. | ||||
|      * Override this function to update handlers data. | ||||
|      */ | ||||
|     updateData(): any { | ||||
|         // To be overridden.
 | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export interface CoreDelegateHandler { | ||||
|     /** | ||||
|      * Name of the handler, or name and sub context (AddonMessages, AddonMessages:blockContact, ...). | ||||
|      * This name will be used to check if the feature is disabled. | ||||
|      */ | ||||
|     name: string; | ||||
| 
 | ||||
|     /** | ||||
|      * Whether or not the handler is enabled on a site level. | ||||
|      * @return Whether or not the handler is enabled on a site level. | ||||
|      */ | ||||
|     isEnabled(): boolean | Promise<boolean>; | ||||
| } | ||||
							
								
								
									
										33
									
								
								src/app/classes/error.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/app/classes/error.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,33 @@ | ||||
| // (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.
 | ||||
| 
 | ||||
| /** | ||||
|  * Base Error class. | ||||
|  * | ||||
|  * The native Error class cannot be extended in Typescript without restoring the prototype chain, extend this | ||||
|  * class instead. | ||||
|  * | ||||
|  * @see https://stackoverflow.com/questions/41102060/typescript-extending-error-class
 | ||||
|  */ | ||||
| export class CoreError extends Error { | ||||
| 
 | ||||
|     constructor(message?: string) { | ||||
|         super(message); | ||||
| 
 | ||||
|         // Fix prototype chain: https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-2.html#support-for-newtarget
 | ||||
|         this.name = new.target.name; | ||||
|         Object.setPrototypeOf(this, new.target.prototype); | ||||
|     } | ||||
| 
 | ||||
| } | ||||
							
								
								
									
										77
									
								
								src/app/classes/interceptor.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										77
									
								
								src/app/classes/interceptor.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,77 @@ | ||||
| // (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 } from '@angular/core'; | ||||
| import { HttpInterceptor, HttpHandler, HttpRequest } from '@angular/common/http'; | ||||
| import { Observable } from 'rxjs'; | ||||
| 
 | ||||
| /** | ||||
|  * Interceptor for Http calls. Adds the header 'Content-Type'='application/x-www-form-urlencoded' | ||||
|  * and serializes the parameters if needed. | ||||
|  */ | ||||
| @Injectable() | ||||
| export class CoreInterceptor implements HttpInterceptor { | ||||
| 
 | ||||
|     /** | ||||
|      * Serialize an object to be used in a request. | ||||
|      * | ||||
|      * @param obj Object to serialize. | ||||
|      * @param addNull Add null values to the serialized as empty parameters. | ||||
|      * @return Serialization of the object. | ||||
|      */ | ||||
|     static serialize(obj: any, addNull?: boolean): string { | ||||
|         let query = ''; | ||||
|         let fullSubName; | ||||
|         let subValue; | ||||
|         let innerObj; | ||||
| 
 | ||||
|         for (const name in obj) { | ||||
|             const value = obj[name]; | ||||
| 
 | ||||
|             if (value instanceof Array) { | ||||
|                 for (let i = 0; i < value.length; ++i) { | ||||
|                     subValue = value[i]; | ||||
|                     fullSubName = name + '[' + i + ']'; | ||||
|                     innerObj = {}; | ||||
|                     innerObj[fullSubName] = subValue; | ||||
|                     query += this.serialize(innerObj) + '&'; | ||||
|                 } | ||||
|             } else if (value instanceof Object) { | ||||
|                 for (const subName in value) { | ||||
|                     subValue = value[subName]; | ||||
|                     fullSubName = name + '[' + subName + ']'; | ||||
|                     innerObj = {}; | ||||
|                     innerObj[fullSubName] = subValue; | ||||
|                     query += this.serialize(innerObj) + '&'; | ||||
|                 } | ||||
|             } else if (addNull || (typeof value != 'undefined' && value !== null)) { | ||||
|                 query += encodeURIComponent(name) + '=' + encodeURIComponent(value) + '&'; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         return query.length ? query.substr(0, query.length - 1) : query; | ||||
|     } | ||||
| 
 | ||||
|     intercept(req: HttpRequest<any>, next: HttpHandler): Observable<any> { | ||||
|         // Add the header and serialize the body if needed.
 | ||||
|         const newReq = req.clone({ | ||||
|             headers: req.headers.set('Content-Type', 'application/x-www-form-urlencoded'), | ||||
|             body: typeof req.body == 'object' && String(req.body) != '[object File]' ? | ||||
|                 CoreInterceptor.serialize(req.body) : req.body | ||||
|         }); | ||||
| 
 | ||||
|         // Pass on the cloned request instead of the original request.
 | ||||
|         return next.handle(newReq); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										98
									
								
								src/app/classes/native-to-angular-http.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/app/classes/native-to-angular-http.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,98 @@ | ||||
| // (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 { HttpResponse as AngularHttpResponse, HttpHeaders } from '@angular/common/http'; | ||||
| import { HTTPResponse as NativeHttpResponse } from '@ionic-native/http'; | ||||
| 
 | ||||
| const HTTP_STATUS_MESSAGES = { | ||||
|     100: 'Continue', | ||||
|     101: 'Switching Protocol', | ||||
|     102: 'Processing', | ||||
|     103: 'Early Hints', | ||||
|     200: 'OK', | ||||
|     201: 'Created', | ||||
|     202: 'Accepted', | ||||
|     203: 'Non-Authoritative Information', | ||||
|     204: 'No Content', | ||||
|     205: 'Reset Content', | ||||
|     206: 'Partial Content', | ||||
|     207: 'Multi-Status', | ||||
|     208: 'Already Reported', | ||||
|     226: 'IM Used', | ||||
|     300: 'Multiple Choice', | ||||
|     301: 'Moved Permanently', | ||||
|     302: 'Found', | ||||
|     303: 'See Other', | ||||
|     304: 'Not Modified', | ||||
|     305: 'Use Proxy', | ||||
|     306: 'unused', | ||||
|     307: 'Temporary Redirect', | ||||
|     308: 'Permanent Redirect', | ||||
|     400: 'Bad Request', | ||||
|     401: 'Unauthorized', | ||||
|     402: 'Payment Required', | ||||
|     403: 'Forbidden', | ||||
|     404: 'Not Found', | ||||
|     405: 'Method Not Allowed', | ||||
|     406: 'Not Acceptable', | ||||
|     407: 'Proxy Authentication Required', | ||||
|     408: 'Request Timeout', | ||||
|     409: 'Conflict', | ||||
|     410: 'Gone', | ||||
|     411: 'Length Required', | ||||
|     412: 'Precondition Failed', | ||||
|     413: 'Payload Too Large', | ||||
|     414: 'URI Too Long', | ||||
|     415: 'Unsupported Media Type', | ||||
|     416: 'Range Not Satisfiable', | ||||
|     417: 'Expectation Failed', | ||||
|     418: 'I\'m a teapot', | ||||
|     421: 'Misdirected Request', | ||||
|     422: 'Unprocessable Entity', | ||||
|     423: 'Locked', | ||||
|     424: 'Failed Dependency', | ||||
|     425: 'Too Early', | ||||
|     426: 'Upgrade Required', | ||||
|     428: 'Precondition Required', | ||||
|     429: 'Too Many Requests', | ||||
|     431: 'Request Header Fields Too Large', | ||||
|     451: 'Unavailable For Legal Reasons', | ||||
|     500: 'Internal Server Error', | ||||
|     501: 'Not Implemented', | ||||
|     502: 'Bad Gateway', | ||||
|     503: 'Service Unavailable', | ||||
|     504: 'Gateway Timeout', | ||||
|     505: 'HTTP Version Not Supported', | ||||
|     506: 'Variant Also Negotiates', | ||||
|     507: 'Insufficient Storage', | ||||
|     508: 'Loop Detected', | ||||
|     510: 'Not Extended', | ||||
|     511: 'Network Authentication Required', | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Class that adapts a Cordova plugin http response to an Angular http response. | ||||
|  */ | ||||
| export class CoreNativeToAngularHttpResponse<T> extends AngularHttpResponse<T> { | ||||
| 
 | ||||
|     constructor(protected nativeResponse: NativeHttpResponse) { | ||||
|         super({ | ||||
|             body: nativeResponse.data, | ||||
|             headers: new HttpHeaders(nativeResponse.headers), | ||||
|             status: nativeResponse.status, | ||||
|             statusText: HTTP_STATUS_MESSAGES[nativeResponse.status] || '', | ||||
|             url: nativeResponse.url || '' | ||||
|         }); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										143
									
								
								src/app/classes/queue-runner.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										143
									
								
								src/app/classes/queue-runner.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,143 @@ | ||||
| // (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 { CoreUtils, PromiseDefer } from '@services/utils/utils'; | ||||
| 
 | ||||
| /** | ||||
|  * Function to add to the queue. | ||||
|  */ | ||||
| export type CoreQueueRunnerFunction<T> = (...args: any[]) => T | Promise<T>; | ||||
| 
 | ||||
| /** | ||||
|  * Queue item. | ||||
|  */ | ||||
| export type CoreQueueRunnerItem<T = any> = { | ||||
|     /** | ||||
|      * Item ID. | ||||
|      */ | ||||
|     id: string; | ||||
| 
 | ||||
|     /** | ||||
|      * Function to execute. | ||||
|      */ | ||||
|     fn: CoreQueueRunnerFunction<T>; | ||||
| 
 | ||||
|     /** | ||||
|      * Deferred with a promise resolved/rejected with the result of the function. | ||||
|      */ | ||||
|     deferred: PromiseDefer<T>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Options to pass to add item. | ||||
|  */ | ||||
| export type CoreQueueRunnerAddOptions = { | ||||
|     /** | ||||
|      * Whether to allow having multiple entries with same ID in the queue. | ||||
|      */ | ||||
|     allowRepeated?: boolean; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * A queue to prevent having too many concurrent executions. | ||||
|  */ | ||||
| export class CoreQueueRunner { | ||||
|     protected queue: {[id: string]: CoreQueueRunnerItem} = {}; | ||||
|     protected orderedQueue: CoreQueueRunnerItem[] = []; | ||||
|     protected numberRunning = 0; | ||||
| 
 | ||||
|     constructor(protected maxParallel: number = 1) { } | ||||
| 
 | ||||
|     /** | ||||
|      * Get unique ID. | ||||
|      * | ||||
|      * @param id ID. | ||||
|      * @return Unique ID. | ||||
|      */ | ||||
|     protected getUniqueId(id: string): string { | ||||
|         let newId = id; | ||||
|         let num = 1; | ||||
| 
 | ||||
|         do { | ||||
|             newId = id + '-' + num; | ||||
|             num++; | ||||
|         } while (newId in this.queue); | ||||
| 
 | ||||
|         return newId; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Process next item in the queue. | ||||
|      * | ||||
|      * @return Promise resolved when next item has been treated. | ||||
|      */ | ||||
|     protected async processNextItem(): Promise<void> { | ||||
|         if (!this.orderedQueue.length || this.numberRunning >= this.maxParallel) { | ||||
|             // Queue is empty or max number of parallel runs reached, stop.
 | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         const item = this.orderedQueue.shift(); | ||||
|         this.numberRunning++; | ||||
| 
 | ||||
|         try { | ||||
|             const result = await item.fn(); | ||||
| 
 | ||||
|             item.deferred.resolve(result); | ||||
|         } catch (error) { | ||||
|             item.deferred.reject(error); | ||||
|         } finally { | ||||
|             delete this.queue[item.id]; | ||||
|             this.numberRunning--; | ||||
| 
 | ||||
|             this.processNextItem(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Add an item to the queue. | ||||
|      * | ||||
|      * @param id ID. | ||||
|      * @param fn Function to call. | ||||
|      * @param options Options. | ||||
|      * @return Promise resolved when the function has been executed. | ||||
|      */ | ||||
|     run<T>(id: string, fn: CoreQueueRunnerFunction<T>, options?: CoreQueueRunnerAddOptions): Promise<T> { | ||||
|         options = options || {}; | ||||
| 
 | ||||
|         if (id in this.queue) { | ||||
|             if (!options.allowRepeated) { | ||||
|                 // Item already in queue, return its promise.
 | ||||
|                 return this.queue[id].deferred.promise; | ||||
|             } | ||||
| 
 | ||||
|             id = this.getUniqueId(id); | ||||
|         } | ||||
| 
 | ||||
|         // Add the item in the queue.
 | ||||
|         const item = { | ||||
|             id, | ||||
|             fn, | ||||
|             deferred: CoreUtils.instance.promiseDefer<T>(), | ||||
|         }; | ||||
| 
 | ||||
|         this.queue[id] = item; | ||||
|         this.orderedQueue.push(item); | ||||
| 
 | ||||
|         // Process next item if we haven't reached the max yet.
 | ||||
|         this.processNextItem(); | ||||
| 
 | ||||
|         return item.deferred.promise; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										2057
									
								
								src/app/classes/site.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2057
									
								
								src/app/classes/site.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1027
									
								
								src/app/classes/sqlitedb.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1027
									
								
								src/app/classes/sqlitedb.ts
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -12,9 +12,32 @@ | ||||
| // See the License for the specific language governing permissions and
 | ||||
| // limitations under the License.
 | ||||
| 
 | ||||
| import { Injector } from '@angular/core'; | ||||
| import { Injector, NgZone as NgZoneService } from '@angular/core'; | ||||
| import { HttpClient } from '@angular/common/http'; | ||||
| 
 | ||||
| import { SplashScreen as SplashScreenPlugin } from '@ionic-native/splash-screen/ngx'; | ||||
| import { Platform as PlatformService } from '@ionic/angular'; | ||||
| 
 | ||||
| import { Clipboard as ClipboardService } from '@ionic-native/clipboard/ngx'; | ||||
| import { Diagnostic as DiagnosticService } from '@ionic-native/diagnostic/ngx'; | ||||
| import { Device as DeviceService } from '@ionic-native/device/ngx'; | ||||
| import { File as FileService } from '@ionic-native/file/ngx'; | ||||
| import { FileOpener as FileOpenerService } from '@ionic-native/file-opener/ngx'; | ||||
| import { FileTransfer as FileTransferService } from '@ionic-native/file-transfer/ngx'; | ||||
| import { Geolocation as GeolocationService } from '@ionic-native/geolocation/ngx'; | ||||
| import { Globalization as GlobalizationService } from '@ionic-native/globalization/ngx'; | ||||
| import { InAppBrowser as InAppBrowserService } from '@ionic-native/in-app-browser/ngx'; | ||||
| import { Keyboard as KeyboardService } from '@ionic-native/keyboard/ngx'; | ||||
| import { LocalNotifications as LocalNotificationsService } from '@ionic-native/local-notifications/ngx'; | ||||
| import { Network as NetworkService } from '@ionic-native/network/ngx'; | ||||
| import { Push as PushService } from '@ionic-native/push/ngx'; | ||||
| import { QRScanner as QRScannerService } from '@ionic-native/qr-scanner/ngx'; | ||||
| import { StatusBar as StatusBarService } from '@ionic-native/status-bar/ngx'; | ||||
| import { SplashScreen as SplashScreenService } from '@ionic-native/splash-screen/ngx'; | ||||
| import { SQLite as SQLiteService } from '@ionic-native/sqlite/ngx'; | ||||
| import { WebIntent as WebIntentService } from '@ionic-native/web-intent/ngx'; | ||||
| import { Zip as ZipService } from '@ionic-native/zip/ngx'; | ||||
| 
 | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| 
 | ||||
| import { CoreSingletonsFactory, CoreInjectionToken, CoreSingletonClass } from '@classes/singletons-factory'; | ||||
| 
 | ||||
| @ -39,4 +62,31 @@ export function makeSingleton<Service>(injectionToken: CoreInjectionToken<Servic | ||||
|     return factory.makeSingleton(injectionToken); | ||||
| } | ||||
| 
 | ||||
| export class SplashScreen extends makeSingleton(SplashScreenPlugin) {} | ||||
| // Convert ionic-native services to singleton.
 | ||||
| export class Clipboard extends makeSingleton(ClipboardService) {} | ||||
| export class Device extends makeSingleton(DeviceService) {} | ||||
| export class Diagnostic extends makeSingleton(DiagnosticService) {} | ||||
| export class File extends makeSingleton(FileService) {} | ||||
| export class FileOpener extends makeSingleton(FileOpenerService) {} | ||||
| export class FileTransfer extends makeSingleton(FileTransferService) {} | ||||
| export class Geolocation extends makeSingleton(GeolocationService) {} | ||||
| export class Globalization extends makeSingleton(GlobalizationService) {} | ||||
| export class InAppBrowser extends makeSingleton(InAppBrowserService) {} | ||||
| export class Keyboard extends makeSingleton(KeyboardService) {} | ||||
| export class LocalNotifications extends makeSingleton(LocalNotificationsService) {} | ||||
| export class Network extends makeSingleton(NetworkService) {} | ||||
| export class Push extends makeSingleton(PushService) {} | ||||
| export class QRScanner extends makeSingleton(QRScannerService) {} | ||||
| export class StatusBar extends makeSingleton(StatusBarService) {} | ||||
| export class SplashScreen extends makeSingleton(SplashScreenService) {} | ||||
| export class SQLite extends makeSingleton(SQLiteService) {} | ||||
| export class WebIntent extends makeSingleton(WebIntentService) {} | ||||
| export class Zip extends makeSingleton(ZipService) {} | ||||
| 
 | ||||
| // Convert some Angular and Ionic injectables to singletons.
 | ||||
| export class NgZone extends makeSingleton(NgZoneService) {} | ||||
| export class Http extends makeSingleton(HttpClient) {} | ||||
| export class Platform extends makeSingleton(PlatformService) {} | ||||
| 
 | ||||
| // Convert external libraries injectables.
 | ||||
| export class Translate extends makeSingleton(TranslateService) {} | ||||
|  | ||||
| @ -43,6 +43,7 @@ | ||||
|         ] | ||||
|       } | ||||
|     ], | ||||
|     "no-angle-bracket-type-assertion": false, | ||||
|     "no-console": [ | ||||
|       true, | ||||
|       "debug", | ||||
| @ -58,12 +59,15 @@ | ||||
|     ], | ||||
|     "no-non-null-assertion": true, | ||||
|     "no-redundant-jsdoc": true, | ||||
|     "no-shadowed-variable": false, | ||||
|     "no-switch-case-fall-through": true, | ||||
|     "no-unused-expression": false, | ||||
|     "no-var-requires": false, | ||||
|     "object-literal-key-quotes": [ | ||||
|       true, | ||||
|       "as-needed" | ||||
|     ], | ||||
|     "prefer-for-of": false, | ||||
|     "quotemark": [ | ||||
|       true, | ||||
|       "single" | ||||
| @ -104,7 +108,8 @@ | ||||
|       "options": [ | ||||
|         "ban-keywords", | ||||
|         "check-format", | ||||
|         "allow-pascal-case" | ||||
|         "allow-pascal-case", | ||||
|         "allow-leading-underscore" | ||||
|       ] | ||||
|     }, | ||||
|     "whitespace": { | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user