From dfbf591e2a16ea525501208cecbc835e0d93c748 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Fri, 31 May 2024 16:05:59 +0200 Subject: [PATCH 1/2] MOBILE-4470 icon: Revert load SVG directly and use img and filters --- src/core/components/mod-icon/mod-icon.html | 9 +- src/core/components/mod-icon/mod-icon.scss | 22 +-- src/core/components/mod-icon/mod-icon.ts | 149 --------------------- src/theme/globals.variables.scss | 9 ++ src/theme/theme.dark.scss | 1 - src/theme/theme.light.scss | 3 +- 6 files changed, 20 insertions(+), 173 deletions(-) diff --git a/src/core/components/mod-icon/mod-icon.html b/src/core/components/mod-icon/mod-icon.html index 0a58c0b76..e4266da4a 100644 --- a/src/core/components/mod-icon/mod-icon.html +++ b/src/core/components/mod-icon/mod-icon.html @@ -1,6 +1,3 @@ - - - - -
+ + diff --git a/src/core/components/mod-icon/mod-icon.scss b/src/core/components/mod-icon/mod-icon.scss index d10806744..7d79dd7f3 100644 --- a/src/core/components/mod-icon/mod-icon.scss +++ b/src/core/components/mod-icon/mod-icon.scss @@ -23,13 +23,13 @@ background-color: transparent; line-height: var(--size); - --color: var(--activity-base-icon-color); - &.colorize { &.version_current { - @each $type, $value in $activity-icon-colors { - &.#{$type} { - --color: var(--activity#{$type}); + @each $type, $value in $activity-icon-color-filters { + &.#{$type}:not(.branded) { + img { + filter: var(--activity#{$type}); + } } } } @@ -40,7 +40,7 @@ @each $type, $value in $activity-icon-background-colors { &.#{$type}:not(.branded) { background-color: var(--activity-40-#{$type}); - ::ng-deep svg, img { + img { filter: brightness(0) invert(1); } } @@ -57,15 +57,7 @@ --padding-bottom: var(--module-legacy-icon-padding, 8px); } - &.colorize.version_current:not(.branded) { - ::ng-deep svg, - ::ng-deep svg * { - fill: var(--color) !important; - } - } - - img, - ::ng-deep svg { + img { width: var(--size); height: var(--size); max-width: var(--size); diff --git a/src/core/components/mod-icon/mod-icon.ts b/src/core/components/mod-icon/mod-icon.ts index 6be57523b..0bb66e0b0 100644 --- a/src/core/components/mod-icon/mod-icon.ts +++ b/src/core/components/mod-icon/mod-icon.ts @@ -24,17 +24,11 @@ import { SimpleChange, signal, } from '@angular/core'; -import { SafeHtml } from '@angular/platform-browser'; import { CoreCourse } from '@features/course/services/course'; import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate'; -import { CoreFile } from '@services/file'; -import { CoreFileHelper } from '@services/file-helper'; import { CoreSites } from '@services/sites'; import { CoreTextUtils } from '@services/utils/text'; import { CoreUrlUtils } from '@services/utils/url'; -import { CoreUtils } from '@services/utils/utils'; -import { DomSanitizer, Http } from '@singletons'; -import { firstValueFrom } from 'rxjs'; const assetsPath = 'assets/img/'; const fallbackModName = 'external-tool'; @@ -80,9 +74,7 @@ export class CoreModIconComponent implements OnInit, OnChanges { iconUrl = signal(''); modNameTranslated = signal(''); isLocalUrl = signal(false); - svgIcon = signal(''); linkIconWithComponent = signal(false); - loaded = signal(false); protected iconVersion: IconVersion = IconVersion.LEGACY_VERSION; protected purposeClass = ''; @@ -208,8 +200,6 @@ export class CoreModIconComponent implements OnInit, OnChanges { ); this.setBrandedClass(); - - await this.setSVGIcon(); } /** @@ -230,8 +220,6 @@ export class CoreModIconComponent implements OnInit, OnChanges { const path = CoreCourse.getModuleIconsPath(); this.iconUrl.set(path + moduleName + '.svg'); - - await this.setSVGIcon(); } /** @@ -306,141 +294,4 @@ export class CoreModIconComponent implements OnInit, OnChanges { return IconVersion.CURRENT_VERSION; } - /** - * Sets SVG markup for the icon (if the URL is an SVG). - * - * @returns Promise resolved when done. - */ - protected async setSVGIcon(): Promise { - if (this.iconVersion === IconVersion.LEGACY_VERSION) { - this.loaded.set(true); - this.svgIcon.set(''); - - return; - } - - this.loaded.set(false); - - let mimetype = ''; - let fileContents = ''; - - // Download the icon if it's not local to cache it. - if (!this.isLocalUrl()) { - try { - const iconUrl = await CoreFileHelper.downloadFile( - this.iconUrl(), - this.linkIconWithComponent() ? this.modname : undefined, - this.linkIconWithComponent() ? this.componentId : undefined, - ); - if (iconUrl) { - mimetype = await CoreUtils.getMimeTypeFromUrl(iconUrl); - fileContents = await CoreFile.readFile(iconUrl); - } - } catch { - // Ignore errors. - } - } - - try { - - if (!fileContents) { - // Try to download the icon directly (also for local files). - const response = await firstValueFrom(Http.get( - this.iconUrl(), - { - observe: 'response', - responseType: 'text', - }, - )); - mimetype = response.headers.get('content-type') || mimetype; - fileContents = response.body || ''; - } - - if (mimetype !== 'image/svg+xml' || !fileContents) { - this.svgIcon.set(''); - - return; - } - - // Clean the DOM to avoid security issues. - const parser = new DOMParser(); - const doc = parser.parseFromString(fileContents, 'image/svg+xml'); - - // Safety check. - if (doc.documentElement.nodeName !== 'svg') { - this.svgIcon.set(''); - - return; - } - - // Remove scripts tags. - const scripts = doc.documentElement.getElementsByTagName('script'); - for (let i = scripts.length - 1; i >= 0; i--) { - scripts[i].parentNode?.removeChild(scripts[i]); - } - - // Has own styles, do not apply colors. - if (doc.documentElement.getElementsByTagName('style').length > 0) { - this.brandedClass = true; - } - - // Recursively remove attributes starting with on. - const removeAttributes = (element: Element): void => { - Array.from(element.attributes).forEach((attr) => { - if (attr.name.startsWith('on')) { - element.removeAttribute(attr.name); - } - }); - - Array.from(element.children).forEach((child) => { - removeAttributes(child); - }); - }; - removeAttributes(doc.documentElement); - - // Add viewBox to avoid scaling issues. - if (!doc.documentElement.getAttribute('viewBox')) { - const width = doc.documentElement.getAttribute('width'); - const height = doc.documentElement.getAttribute('height'); - if (width && height) { - doc.documentElement.setAttribute('viewBox', '0 0 '+ width + ' ' + height); - } - } - - // Prefix id's on svg DOM to avoid conflicts. - const uniqueId = 'modicon' + CoreUtils.getUniqueId('modicon') + '_'; - const styleTags = Array.from(doc.documentElement.getElementsByTagName('style')); - const styleAttrs = Array.from(doc.documentElement.querySelectorAll('[style]')); - const idTags = Array.from(doc.documentElement.querySelectorAll('[id]')); - idTags.forEach((element) => { - if (!element.id) { - return; - } - const newId = uniqueId + element.id; - // Regexp to replace all ocurrences of the id with workd bondaries. - const oldIdFinder = new RegExp(`#${element.id}\\b`, 'g'); - - element.id = newId; - - // Prefix the elementId on style Tags. - styleTags.forEach((style) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - style.textContent = style.textContent!.replace(oldIdFinder, `#${newId}`); - }); - - // Also change ids on style attributes. - styleAttrs.forEach((attr) => { - // eslint-disable-next-line @typescript-eslint/no-non-null-assertion - attr.setAttribute('style', attr.getAttribute('style')!.replace(oldIdFinder, `#${newId}`)); - }); - }); - - this.svgIcon.set(DomSanitizer.bypassSecurityTrustHtml(doc.documentElement.outerHTML)); - } catch { - this.svgIcon.set(''); - } finally { - this.loaded.set(true); - } - } - } diff --git a/src/theme/globals.variables.scss b/src/theme/globals.variables.scss index 815179140..3cebbc93b 100644 --- a/src/theme/globals.variables.scss +++ b/src/theme/globals.variables.scss @@ -136,6 +136,15 @@ $activity-icon-colors: ( interactivecontent: #8d3d1b ) !default; +$activity-icon-color-filters: ( + administration: brightness(0%) invert(45%) sepia(46%) saturate(3819%) hue-rotate(260deg) brightness(101%) contrast(87%), + assessment: brightness(0%) invert(36%) sepia(98%) saturate(6969%) hue-rotate(315deg) brightness(90%) contrast(119%), + collaboration: brightness(0%) invert(25%) sepia(54%) saturate(6226%) hue-rotate(245deg) brightness(100%) contrast(102%), + communication: brightness(0%) invert(48%) sepia(74%) saturate(4887%) hue-rotate(11deg) brightness(102%) contrast(101%), + content: brightness(0%) invert(49%) sepia(52%) saturate(4675%) hue-rotate(156deg) brightness(89%) contrast(102%), + interactivecontent: brightness(0%) invert(25%) sepia(63%) saturate(1152%) hue-rotate(344deg) brightness(94%) contrast(91%) +) !default; + $calendar-event-category-category: #8e24aa !default; $calendar-event-category-course: $red !default; $calendar-event-category-group: $yellow !default; diff --git a/src/theme/theme.dark.scss b/src/theme/theme.dark.scss index 95d463e6e..f2836b6b9 100644 --- a/src/theme/theme.dark.scss +++ b/src/theme/theme.dark.scss @@ -172,5 +172,4 @@ html.dark { --core-table-even-cell-background: var(--gray-900); --core-table-even-cell-hover: var(--gray-700); - --activity-base-icon-color: var(--white); } diff --git a/src/theme/theme.light.scss b/src/theme/theme.light.scss index 74bb7b704..919eb588d 100644 --- a/src/theme/theme.light.scss +++ b/src/theme/theme.light.scss @@ -201,9 +201,8 @@ html { --core-dd-question-color-#{$i + 1}-contrast: #{get_contrast_color(nth($core-dd-question-colors, $i + 1))}; } - --activity-base-icon-color: var(--gray-900); // Make activtity colours available for custom modules. - @each $type, $value in $activity-icon-colors { + @each $type, $value in $activity-icon-color-filters { --activity#{$type}: #{$value}; } From df6b6788d6353d8fbf9ac8197fd5443b0a976965 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pau=20Ferrer=20Oca=C3=B1a?= Date: Mon, 3 Jun 2024 10:45:57 +0200 Subject: [PATCH 2/2] MOBILE-4470 chore: Fix HTML missing fields --- .../rich-text-editor/core-editor-rich-text-editor.html | 2 +- src/core/features/login/components/sites-modal/sites-modal.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html b/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html index 54444472b..33f446b6d 100644 --- a/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html +++ b/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html @@ -5,7 +5,7 @@
diff --git a/src/core/features/login/components/sites-modal/sites-modal.html b/src/core/features/login/components/sites-modal/sites-modal.html index 010f99a84..fb72845c5 100644 --- a/src/core/features/login/components/sites-modal/sites-modal.html +++ b/src/core/features/login/components/sites-modal/sites-modal.html @@ -23,7 +23,7 @@ - +