diff --git a/src/core/components/iframe/iframe.ts b/src/core/components/iframe/iframe.ts index 58fd3f82a..32b7fc156 100644 --- a/src/core/components/iframe/iframe.ts +++ b/src/core/components/iframe/iframe.ts @@ -48,8 +48,8 @@ export class CoreIframeComponent implements OnChanges, OnDestroy { @Input() src?: string; @Input() id: string | null = null; - @Input() iframeWidth?: string; - @Input() iframeHeight?: string; + @Input() iframeWidth = '100%'; + @Input() iframeHeight = '100%'; @Input() allowFullscreen?: boolean | string; @Input() showFullscreenOnToolbar?: boolean | string; @Input() autoFullscreenOnRotate?: boolean | string; diff --git a/src/core/components/tabs-outlet/tabs-outlet.ts b/src/core/components/tabs-outlet/tabs-outlet.ts index 0deddc47e..92c2d696d 100644 --- a/src/core/components/tabs-outlet/tabs-outlet.ts +++ b/src/core/components/tabs-outlet/tabs-outlet.ts @@ -30,6 +30,7 @@ import { StackDidChangeEvent } from '@ionic/angular/common/directives/navigation import { CoreNavigator } from '@services/navigator'; import { CoreTabBase, CoreTabsBaseComponent } from '@classes/tabs'; import { CoreDirectivesRegistry } from '@singletons/directives-registry'; +import { CorePath } from '@singletons/path'; /** * This component displays some top scrollable tabs that will autohide on vertical scroll. @@ -143,6 +144,14 @@ export class CoreTabsOutletComponent extends CoreTabsBaseComponent
+ @if (dataUrl) { + + } @else { + }
diff --git a/src/core/features/viewer/components/image/image.ts b/src/core/features/viewer/components/image/image.ts index f52e9ab52..87deee8c7 100644 --- a/src/core/features/viewer/components/image/image.ts +++ b/src/core/features/viewer/components/image/image.ts @@ -13,11 +13,12 @@ // limitations under the License. import { Component, ElementRef, Input, OnInit, ViewChild } from '@angular/core'; -import { ModalController, Translate } from '@singletons'; +import { DomSanitizer, ModalController, Translate } from '@singletons'; import { CoreMath } from '@singletons/math'; import { Swiper } from 'swiper'; import { SwiperOptions } from 'swiper/types'; import { CoreSwiper } from '@singletons/swiper'; +import { SafeResourceUrl } from '@angular/platform-browser'; /** * Modal component to view an image. @@ -52,6 +53,8 @@ export class CoreViewerImageComponent implements OnInit { @Input() component?: string; // Component to use in external-content. @Input() componentId?: string | number; // Component ID to use in external-content. + dataUrl?: SafeResourceUrl; + private static readonly MAX_RATIO = 8; private static readonly MIN_RATIO = 0.5; @@ -72,6 +75,12 @@ export class CoreViewerImageComponent implements OnInit { */ ngOnInit(): void { this.title = this.title || Translate.instant('core.imageviewer'); + + if (this.image.startsWith('data:')) { + // It's a data image, sanitize it so it can be rendered. + // Don't sanitize other images because they load fine and they need to be treated by core-external-content. + this.dataUrl = DomSanitizer.bypassSecurityTrustResourceUrl(this.image); + } } /** diff --git a/src/core/singletons/path.ts b/src/core/singletons/path.ts index 01e584e31..6211a6327 100644 --- a/src/core/singletons/path.ts +++ b/src/core/singletons/path.ts @@ -99,4 +99,22 @@ export class CorePath { } } + /** + * Check if a certain path is the ancestor of another path. + * + * @param ancestorPath Ancestor path. + * @param path Path to check. + * @returns Whether the path is an ancestor of the other path. + */ + static pathIsAncestor(ancestorPath: string, path: string): boolean { + const ancestorSplit = CoreText.removeEndingSlash(ancestorPath).split('/'); + const pathSplit = CoreText.removeEndingSlash(path).split('/'); + + if (ancestorSplit.length >= pathSplit.length) { + return false; + } + + return !ancestorSplit.some((value, index) => value !== pathSplit[index]); + } + } diff --git a/src/core/singletons/tests/path.test.ts b/src/core/singletons/tests/path.test.ts index 9cee687e0..2800b79ef 100644 --- a/src/core/singletons/tests/path.test.ts +++ b/src/core/singletons/tests/path.test.ts @@ -52,4 +52,13 @@ describe('CorePath', () => { expect(CorePath.concatenatePaths('foo/bar', 'baz')).toEqual('foo/bar/baz'); }); + it('checks ancestor paths', () => { + expect(CorePath.pathIsAncestor('/foo', '/foo/bar')).toEqual(true); + expect(CorePath.pathIsAncestor('/foo/', '/foo/bar')).toEqual(true); + expect(CorePath.pathIsAncestor('/foo', '/foo/bar/baz')).toEqual(true); + expect(CorePath.pathIsAncestor('/foo/baz', '/foo/bar')).toEqual(false); + expect(CorePath.pathIsAncestor('/foo/bar', '/foo/bar')).toEqual(false); + expect(CorePath.pathIsAncestor('/foo/b', '/foo/bar')).toEqual(false); + }); + });