Merge pull request #2802 from NoelDeMartin/MOBILE-3766
MOBILE-3766 more: Allow defining items in config
This commit is contained in:
		
						commit
						bf31840d56
					
				| @ -15,6 +15,7 @@ | ||||
| /* eslint-disable @typescript-eslint/naming-convention */ | ||||
| 
 | ||||
| import { CoreColorScheme, CoreZoomLevel } from '@features/settings/services/settings-helper'; | ||||
| import { CoreMainMenuLocalizedCustomItem } from '@features/mainmenu/services/mainmenu'; | ||||
| import { CoreSitesDemoSiteData } from '@services/sites'; | ||||
| import envJson from '@/assets/env.json'; | ||||
| import { OpenFileAction } from '@services/utils/utils'; | ||||
| @ -175,6 +176,7 @@ export interface EnvironmentConfig { | ||||
|     displayqronsitescreen?: boolean; | ||||
|     forceOpenLinksIn: 'app' | 'browser'; | ||||
|     iOSDefaultOpenFileAction?: OpenFileAction; | ||||
|     customMainMenuItems?: CoreMainMenuLocalizedCustomItem[]; | ||||
| }; | ||||
| 
 | ||||
| export interface EnvironmentBuild { | ||||
|  | ||||
| @ -15,11 +15,13 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| 
 | ||||
| import { CoreApp } from '@services/app'; | ||||
| import { CoreLang } from '@services/lang'; | ||||
| import { CoreLang, CoreLangLanguage } from '@services/lang'; | ||||
| import { CoreSites } from '@services/sites'; | ||||
| import { CoreConstants } from '@/core/constants'; | ||||
| import { CoreMainMenuDelegate, CoreMainMenuHandlerToDisplay } from './mainmenu-delegate'; | ||||
| import { makeSingleton } from '@singletons'; | ||||
| import { Device, makeSingleton } from '@singletons'; | ||||
| import { CoreArray } from '@singletons/array'; | ||||
| import { CoreTextUtils } from '@services/utils/text'; | ||||
| 
 | ||||
| /** | ||||
|  * Service that provides some features regarding Main Menu. | ||||
| @ -48,13 +50,28 @@ export class CoreMainMenuProvider { | ||||
|         return handlers.filter(handler => !handler.onlyInMore).slice(0, this.getNumItems()); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a list of custom menu items. | ||||
|      * | ||||
|      * @param siteId Site to get custom items from. | ||||
|      * @return List of custom menu items. | ||||
|      */ | ||||
|     async getCustomMenuItems(siteId?: string): Promise<CoreMainMenuCustomItem[]> { | ||||
|         const customItems = await Promise.all([ | ||||
|             this.getCustomMenuItemsFromSite(siteId), | ||||
|             this.getCustomItemsFromConfig(), | ||||
|         ]); | ||||
| 
 | ||||
|         return CoreArray.flatten(customItems); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a list of custom menu items for a certain site. | ||||
|      * | ||||
|      * @param siteId Site ID. If not defined, current site. | ||||
|      * @return List of custom menu items. | ||||
|      */ | ||||
|     async getCustomMenuItems(siteId?: string): Promise<CoreMainMenuCustomItem[]> { | ||||
|     protected async getCustomMenuItemsFromSite(siteId?: string): Promise<CoreMainMenuCustomItem[]> { | ||||
|         const site = await CoreSites.getSite(siteId); | ||||
| 
 | ||||
|         const itemsString = site.getStoredConfig('tool_mobile_custommenuitems'); | ||||
| @ -148,6 +165,45 @@ export class CoreMainMenuProvider { | ||||
|         return result.filter((entry) => typeof entry != 'undefined'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get a list of custom menu items from config. | ||||
|      * | ||||
|      * @return List of custom menu items. | ||||
|      */ | ||||
|     protected async getCustomItemsFromConfig(): Promise<CoreMainMenuCustomItem[]> { | ||||
|         const items = CoreConstants.CONFIG.customMainMenuItems; | ||||
| 
 | ||||
|         if (!items) { | ||||
|             return []; | ||||
|         } | ||||
| 
 | ||||
|         const currentLang = await CoreLang.getCurrentLanguage(); | ||||
| 
 | ||||
|         const fallbackLang = CoreConstants.CONFIG.default_lang || 'en'; | ||||
|         const replacements = { | ||||
|             devicetype: '', | ||||
|             osversion: Device.version, | ||||
|         }; | ||||
| 
 | ||||
|         if (CoreApp.isAndroid()) { | ||||
|             replacements.devicetype = 'Android'; | ||||
|         } else if (CoreApp.isIOS()) { | ||||
|             replacements.devicetype = 'iPhone or iPad'; | ||||
|         } else { | ||||
|             replacements.devicetype = 'Other'; | ||||
|         } | ||||
| 
 | ||||
|         return items | ||||
|             .filter(item => typeof item.label === 'string' || currentLang in item.label || fallbackLang in item.label) | ||||
|             .map(item => ({ | ||||
|                 ...item, | ||||
|                 url: CoreTextUtils.replaceArguments(item.url, replacements, 'uri'), | ||||
|                 label: typeof item.label === 'string' | ||||
|                     ? item.label | ||||
|                     : item.label[currentLang] ?? item.label[fallbackLang], | ||||
|             })); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Get the number of items to be shown on the main menu bar. | ||||
|      * | ||||
| @ -264,6 +320,13 @@ export interface CoreMainMenuCustomItem { | ||||
|     icon: string; | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|  * Custom main menu item with localized text. | ||||
|  */ | ||||
| export type CoreMainMenuLocalizedCustomItem = Omit<CoreMainMenuCustomItem, 'label'> & { | ||||
|     label: string | Record<CoreLangLanguage, string>; | ||||
| }; | ||||
| 
 | ||||
| /** | ||||
|  * Map of custom menu items. | ||||
|  */ | ||||
|  | ||||
| @ -480,7 +480,7 @@ export class CoreLangProvider { | ||||
|      * @param lang Language code. | ||||
|      * @return Promise resolved with the file contents. | ||||
|      */ | ||||
|     async readLangFile(lang: string): Promise<Record<string, string>> { | ||||
|     async readLangFile(lang: CoreLangLanguage): Promise<Record<string, string>> { | ||||
|         const observable = Http.get(`assets/lang/${lang}.json`, { | ||||
|             responseType: 'json', | ||||
|         }); | ||||
| @ -519,6 +519,11 @@ export class CoreLangProvider { | ||||
| 
 | ||||
| export const CoreLang = makeSingleton(CoreLangProvider); | ||||
| 
 | ||||
| /** | ||||
|  * Language code. E.g. 'au', 'es', etc. | ||||
|  */ | ||||
| export type CoreLangLanguage = string; | ||||
| 
 | ||||
| /** | ||||
|  * Language object has two leves, first per language and second per string key. | ||||
|  */ | ||||
|  | ||||
| @ -93,4 +93,19 @@ describe('CoreTextUtilsProvider', () => { | ||||
|         expect(textUtils.matchesGlob('/foo/bar/baz', '/foo/ba?/ba?')).toBe(true); | ||||
|     }); | ||||
| 
 | ||||
|     it('replaces arguments', () => { | ||||
|         // Arrange
 | ||||
|         const url = 'http://campus.edu?device={{device}}&version={{version}}'; | ||||
|         const replacements = { | ||||
|             device: 'iPhone or iPad', | ||||
|             version: '1.2.3', | ||||
|         }; | ||||
| 
 | ||||
|         // Act
 | ||||
|         const replaced = textUtils.replaceArguments(url, replacements, 'uri'); | ||||
| 
 | ||||
|         // Assert
 | ||||
|         expect(replaced).toEqual('http://campus.edu?device=iPhone%20or%20iPad&version=1.2.3'); | ||||
|     }); | ||||
| 
 | ||||
| }); | ||||
|  | ||||
| @ -731,6 +731,28 @@ export class CoreTextUtilsProvider { | ||||
|         return text.replace(/[#:/?\\]+/g, '_'); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Replace {{ARGUMENT}} arguments in the text. | ||||
|      * | ||||
|      * @param text Text to treat. | ||||
|      * @param replacements Argument values. | ||||
|      * @param encoding Encoding to use in values. | ||||
|      * @returns Treated text. | ||||
|      */ | ||||
|     replaceArguments(text: string, replacements: Record<string, string> = {}, encoding?: 'uri'): string { | ||||
|         let match; | ||||
| 
 | ||||
|         while ((match = text.match(/\{\{([^}]+)\}\}/))) { | ||||
|             const argument = match[1].trim(); | ||||
|             const value = replacements[argument] ?? ''; | ||||
|             const encodedValue = encoding ? encodeURIComponent(value) : value; | ||||
| 
 | ||||
|             text = text.replace(`{{${argument}}}`, encodedValue); | ||||
|         } | ||||
| 
 | ||||
|         return text; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Replace all the new lines on a certain text. | ||||
|      * | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user