+
-
+
diff --git a/src/core/components/mod-icon/mod-icon.ts b/src/core/components/mod-icon/mod-icon.ts
index e8a09cdd0..7de508ef2 100644
--- a/src/core/components/mod-icon/mod-icon.ts
+++ b/src/core/components/mod-icon/mod-icon.ts
@@ -13,7 +13,8 @@
// limitations under the License.
import { CoreConstants, ModPurpose } from '@/core/constants';
-import { Component, ElementRef, HostBinding, Input, OnChanges, OnInit, SimpleChange, ViewChild } from '@angular/core';
+import { Component, ElementRef, HostBinding, Input, OnChanges, OnInit, SimpleChange } 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';
@@ -22,7 +23,7 @@ import { CoreSites } from '@services/sites';
import { CoreTextUtils } from '@services/utils/text';
import { CoreUrlUtils } from '@services/utils/url';
import { CoreUtils } from '@services/utils/utils';
-import { Http } from '@singletons';
+import { DomSanitizer, Http } from '@singletons';
import { firstValueFrom } from 'rxjs';
const assetsPath = 'assets/img/';
@@ -65,13 +66,11 @@ export class CoreModIconComponent implements OnInit, OnChanges {
return this.showAlt ? this.modNameTranslated : '';
}
- @ViewChild('svg') svgElement!: ElementRef;
-
iconUrl = '';
modNameTranslated = '';
isLocalUrl = false;
- svgLoaded = false;
+ svgIcon: SafeHtml = '';
linkIconWithComponent = false;
loaded = false;
@@ -304,7 +303,7 @@ export class CoreModIconComponent implements OnInit, OnChanges {
protected async setSVGIcon(): Promise {
if (this.iconVersion === IconVersion.LEGACY_VERSION) {
this.loaded = true;
- this.svgLoaded = false;
+ this.svgIcon = '';
return;
}
@@ -347,7 +346,7 @@ export class CoreModIconComponent implements OnInit, OnChanges {
}
if (mimetype !== 'image/svg+xml' || !fileContents) {
- this.svgLoaded = false;
+ this.svgIcon = '';
return;
}
@@ -358,7 +357,7 @@ export class CoreModIconComponent implements OnInit, OnChanges {
// Safety check.
if (doc.documentElement.nodeName !== 'svg') {
- this.svgLoaded = false;
+ this.svgIcon = '';
return;
}
@@ -397,10 +396,37 @@ export class CoreModIconComponent implements OnInit, OnChanges {
}
}
- this.svgElement.nativeElement.replaceChildren(doc.documentElement);
- this.svgLoaded = true;
+ // 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 = DomSanitizer.bypassSecurityTrustHtml(doc.documentElement.outerHTML);
} catch {
- this.svgLoaded = false;
+ this.svgIcon = '';
} finally {
this.loaded = true;
}
diff --git a/src/theme/components/ion-modal.scss b/src/theme/components/ion-modal.scss
index 479099b6e..5abc4a544 100644
--- a/src/theme/components/ion-modal.scss
+++ b/src/theme/components/ion-modal.scss
@@ -75,24 +75,24 @@ ion-modal {
--ion-safe-area-left: 0px;
--ion-safe-area-right: 0px;
+ --height: 100% !important;
+ --width: calc(100% - var(--modal-lateral-margin));
+ --box-shadow: 0 28px 48px rgb(0 0 0 / 40%);
+
+ // These lines is intended to hide modal-shadow div only in iOS because it cannot be positioned correctly.
+ // Both are set on content part.
+ --max-height: 0px;
+ --max-width: 0px;
+
&::part(content) {
@include margin-horizontal(var(--modal-lateral-margin), null);
+ --max-width: calc(var(--modal-lateral-max-width));
+ --max-height: 100%;
+
position: absolute;
@include position(0 !important, 0 !important, 0 !important, unset !important);
display: block;
- height: 100% !important;
- width: calc(100% - var(--modal-lateral-margin));
- max-width: calc(var(--modal-lateral-max-width));
- box-shadow: 0 28px 48px rgb(0 0 0 / 40%);
- }
-
- &::part(backdrop) {
- visibility: visible;
- }
-
- .modal-shadow {
- display: none;
}
}
@@ -109,6 +109,10 @@ ion-modal {
--width: 384px;
--height: auto;
+ .ion-page {
+ position: absolute;
+ }
+
form {
display: flex;
flex-direction: column;