forked from CIT/Vmeda.Online
		
	MOBILE-3708 core: Fix and implement some missing todos
This commit is contained in:
		
							parent
							
								
									ad4953f396
								
							
						
					
					
						commit
						400bc6840f
					
				
							
								
								
									
										29
									
								
								src/core/components/bs-tooltip/bs-tooltip.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/core/components/bs-tooltip/bs-tooltip.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,29 @@
 | 
			
		||||
// (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 { Component, Input } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Component to display a Bootstrap Tooltip in a popover.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-bs-tooltip',
 | 
			
		||||
    templateUrl: 'core-bs-tooltip.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreBSTooltipComponent {
 | 
			
		||||
 | 
			
		||||
    @Input() content = '';
 | 
			
		||||
    @Input() html?: boolean;
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6
									
								
								src/core/components/bs-tooltip/core-bs-tooltip.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/core/components/bs-tooltip/core-bs-tooltip.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,6 @@
 | 
			
		||||
<ion-item class="ion-text-wrap">
 | 
			
		||||
    <ion-label>
 | 
			
		||||
        <p *ngIf="html" [innerHTML]="content"></p>
 | 
			
		||||
        <p *ngIf="!html">{{content}}</p>
 | 
			
		||||
    </ion-label>
 | 
			
		||||
</ion-item>
 | 
			
		||||
@ -51,6 +51,7 @@ import { CorePipesModule } from '@pipes/pipes.module';
 | 
			
		||||
import { CoreAttachmentsComponent } from './attachments/attachments';
 | 
			
		||||
import { CoreFilesComponent } from './files/files';
 | 
			
		||||
import { CoreLocalFileComponent } from './local-file/local-file';
 | 
			
		||||
import { CoreBSTooltipComponent } from './bs-tooltip/bs-tooltip';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
@ -84,6 +85,7 @@ import { CoreLocalFileComponent } from './local-file/local-file';
 | 
			
		||||
        CoreAttachmentsComponent,
 | 
			
		||||
        CoreFilesComponent,
 | 
			
		||||
        CoreLocalFileComponent,
 | 
			
		||||
        CoreBSTooltipComponent,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        CommonModule,
 | 
			
		||||
@ -124,6 +126,7 @@ import { CoreLocalFileComponent } from './local-file/local-file';
 | 
			
		||||
        CoreAttachmentsComponent,
 | 
			
		||||
        CoreFilesComponent,
 | 
			
		||||
        CoreLocalFileComponent,
 | 
			
		||||
        CoreBSTooltipComponent,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
export class CoreComponentsModule {}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,6 @@
 | 
			
		||||
ion-app.app-root core-iframe {
 | 
			
		||||
@import "~theme/globals";
 | 
			
		||||
 | 
			
		||||
:host {
 | 
			
		||||
    > div {
 | 
			
		||||
        max-width: 100%;
 | 
			
		||||
        max-height: 100%;
 | 
			
		||||
@ -8,7 +9,7 @@ ion-app.app-root core-iframe {
 | 
			
		||||
        border: 0;
 | 
			
		||||
        display: block;
 | 
			
		||||
        max-width: 100%;
 | 
			
		||||
        background-color: $gray-light;
 | 
			
		||||
        background-color: var(--gray-light);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    .core-loading-container {
 | 
			
		||||
 | 
			
		||||
@ -27,6 +27,7 @@ import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-iframe',
 | 
			
		||||
    templateUrl: 'core-iframe.html',
 | 
			
		||||
    styleUrls: ['iframe.scss'],
 | 
			
		||||
})
 | 
			
		||||
export class CoreIframeComponent implements OnChanges {
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -22,10 +22,10 @@
 | 
			
		||||
                </core-course-module-completion>
 | 
			
		||||
 | 
			
		||||
                <div class="core-module-buttons-more">
 | 
			
		||||
                    <!-- @todo <core-download-refresh [status]="downloadStatus" [enabled]="downloadEnabled"
 | 
			
		||||
                    <core-download-refresh [status]="downloadStatus" [enabled]="downloadEnabled"
 | 
			
		||||
                        [canTrustDownload]="canCheckUpdates" [loading]="spinner || module.handlerData.spinner"
 | 
			
		||||
                        (action)="download($event)">
 | 
			
		||||
                    </core-download-refresh> -->
 | 
			
		||||
                    </core-download-refresh>
 | 
			
		||||
 | 
			
		||||
                    <!-- Buttons defined by the module handler. -->
 | 
			
		||||
                    <ion-button fill="clear" *ngFor="let button of module.handlerData.buttons" color="dark"
 | 
			
		||||
 | 
			
		||||
@ -16,14 +16,14 @@ import { Component, Input, OnInit, OnDestroy } from '@angular/core';
 | 
			
		||||
import { CoreEventCourseStatusChanged, CoreEventObserver, CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreDomUtils } from '@services/utils/dom';
 | 
			
		||||
// import { CoreUser } from '@core/user/services/user';
 | 
			
		||||
import { CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreCourses, CoreCoursesMyCoursesUpdatedEventData, CoreCoursesProvider } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreCourse, CoreCourseProvider } from '@features/course/services/course';
 | 
			
		||||
import { CoreCourseHelper, CorePrefetchStatusInfo } from '@features/course/services/course-helper';
 | 
			
		||||
import { PopoverController, Translate } from '@singletons';
 | 
			
		||||
import { CoreConstants } from '@/core/constants';
 | 
			
		||||
import { CoreEnrolledCourseDataWithExtraInfoAndOptions } from '../../services/courses-helper';
 | 
			
		||||
import { CoreCoursesCourseOptionsMenuComponent } from '../course-options-menu/course-options-menu';
 | 
			
		||||
import { CoreUser } from '@features/user/services/user';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * This component is meant to display a course for a list of courses with progress.
 | 
			
		||||
@ -193,7 +193,6 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
 | 
			
		||||
     * Show the context menu.
 | 
			
		||||
     *
 | 
			
		||||
     * @param e Click Event.
 | 
			
		||||
     * @todo
 | 
			
		||||
     */
 | 
			
		||||
    async showCourseOptionsMenu(e: Event): Promise<void> {
 | 
			
		||||
        e.preventDefault();
 | 
			
		||||
@ -247,22 +246,62 @@ export class CoreCoursesCourseProgressComponent implements OnInit, OnDestroy {
 | 
			
		||||
     * Hide/Unhide the course from the course list.
 | 
			
		||||
     *
 | 
			
		||||
     * @param hide True to hide and false to show.
 | 
			
		||||
     * @todo CoreUser
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    protected setCourseHidden(hide: boolean): void {
 | 
			
		||||
        return;
 | 
			
		||||
    protected async setCourseHidden(hide: boolean): Promise<void> {
 | 
			
		||||
        this.showSpinner = true;
 | 
			
		||||
 | 
			
		||||
        // We should use null to unset the preference.
 | 
			
		||||
        try {
 | 
			
		||||
            await CoreUser.updateUserPreference(
 | 
			
		||||
                'block_myoverview_hidden_course_' + this.course.id,
 | 
			
		||||
                hide ? '1' : undefined,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            this.course.hidden = hide;
 | 
			
		||||
            CoreEvents.trigger<CoreCoursesMyCoursesUpdatedEventData>(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
 | 
			
		||||
                courseId: this.course.id,
 | 
			
		||||
                course: this.course,
 | 
			
		||||
                action: CoreCoursesProvider.ACTION_STATE_CHANGED,
 | 
			
		||||
                state: CoreCoursesProvider.STATE_HIDDEN,
 | 
			
		||||
                value: hide,
 | 
			
		||||
            }, CoreSites.getCurrentSiteId());
 | 
			
		||||
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            if (!this.isDestroyed) {
 | 
			
		||||
                CoreDomUtils.showErrorModalDefault(error, 'Error changing course visibility.');
 | 
			
		||||
            }
 | 
			
		||||
        } finally {
 | 
			
		||||
            this.showSpinner = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Favourite/Unfavourite the course from the course list.
 | 
			
		||||
     *
 | 
			
		||||
     * @param favourite True to favourite and false to unfavourite.
 | 
			
		||||
     * @todo CoreUser
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    protected setCourseFavourite(favourite: boolean): void {
 | 
			
		||||
        return;
 | 
			
		||||
    protected async setCourseFavourite(favourite: boolean): Promise<void> {
 | 
			
		||||
        this.showSpinner = true;
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            await CoreCourses.setFavouriteCourse(this.course.id, favourite);
 | 
			
		||||
 | 
			
		||||
            this.course.isfavourite = favourite;
 | 
			
		||||
            CoreEvents.trigger<CoreCoursesMyCoursesUpdatedEventData>(CoreCoursesProvider.EVENT_MY_COURSES_UPDATED, {
 | 
			
		||||
                courseId: this.course.id,
 | 
			
		||||
                course: this.course,
 | 
			
		||||
                action: CoreCoursesProvider.ACTION_STATE_CHANGED,
 | 
			
		||||
                state: CoreCoursesProvider.STATE_FAVOURITE,
 | 
			
		||||
                value: favourite,
 | 
			
		||||
            }, CoreSites.getCurrentSiteId());
 | 
			
		||||
 | 
			
		||||
        } catch (error) {
 | 
			
		||||
            if (!this.isDestroyed) {
 | 
			
		||||
                CoreDomUtils.showErrorModalDefault(error, 'Error changing course favourite attribute.');
 | 
			
		||||
            }
 | 
			
		||||
        } finally {
 | 
			
		||||
            this.showSpinner = false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -450,11 +450,11 @@ export class CoreCoursesCoursePreviewPage implements OnInit, OnDestroy {
 | 
			
		||||
     * Prefetch the course.
 | 
			
		||||
     */
 | 
			
		||||
    prefetchCourse(): void {
 | 
			
		||||
        /* @todo CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course).catch((error) => {
 | 
			
		||||
        CoreCourseHelper.confirmAndPrefetchCourse(this.prefetchCourseData, this.course!).catch((error) => {
 | 
			
		||||
            if (!this.pageDestroyed) {
 | 
			
		||||
                CoreDomUtils.showErrorModalDefault(error, 'core.course.errordownloadingcourse', true);
 | 
			
		||||
            }
 | 
			
		||||
        });*/
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,8 @@ import { CoreSiteBasicInfo, CoreSites } from '@services/sites';
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
import { CoreLoginHelper } from '@features/login/services/login-helper';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CorePushNotifications } from '@features/pushnotifications/services/pushnotifications';
 | 
			
		||||
import { CoreFilter } from '@features/filter/services/filter';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page that displays a "splash screen" while the app is being initialized.
 | 
			
		||||
@ -48,13 +50,12 @@ export class CoreLoginSitesPage implements OnInit {
 | 
			
		||||
        const sites = await CoreUtils.ignoreErrors(CoreSites.getSortedSites(), [] as CoreSiteBasicInfo[]);
 | 
			
		||||
 | 
			
		||||
        // Remove protocol from the url to show more url text.
 | 
			
		||||
        this.sites = sites.map((site) => {
 | 
			
		||||
        this.sites = await Promise.all(sites.map(async (site) => {
 | 
			
		||||
            site.siteUrl = site.siteUrl.replace(/^https?:\/\//, '');
 | 
			
		||||
            site.badge = 0;
 | 
			
		||||
            // @todo: getSiteCounter.
 | 
			
		||||
            site.badge = await CoreUtils.ignoreErrors(CorePushNotifications.getSiteCounter(site.id)) || 0;
 | 
			
		||||
 | 
			
		||||
            return site;
 | 
			
		||||
        });
 | 
			
		||||
        }));
 | 
			
		||||
 | 
			
		||||
        this.showDelete = false;
 | 
			
		||||
    }
 | 
			
		||||
@ -76,9 +77,9 @@ export class CoreLoginSitesPage implements OnInit {
 | 
			
		||||
    async deleteSite(e: Event, site: CoreSiteBasicInfo): Promise<void> {
 | 
			
		||||
        e.stopPropagation();
 | 
			
		||||
 | 
			
		||||
        const siteName = site.siteName || '';
 | 
			
		||||
        let siteName = site.siteName || '';
 | 
			
		||||
 | 
			
		||||
        // @todo: Format text: siteName.
 | 
			
		||||
        siteName = await CoreFilter.formatText(siteName, { clean: true, singleLine: true, filter: false }, [], site.id);
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
            await CoreDomUtils.showDeleteConfirm('core.login.confirmdeletesite', { sitename: siteName });
 | 
			
		||||
 | 
			
		||||
@ -146,10 +146,7 @@ export class CoreMainMenuMorePage implements OnInit, OnDestroy {
 | 
			
		||||
     * @param item Item to open.
 | 
			
		||||
     */
 | 
			
		||||
    openItem(item: CoreMainMenuCustomItem): void {
 | 
			
		||||
        // @todo CoreNavigator.navigateToSitePath('CoreViewerIframePage', {title: item.label, url: item.url});
 | 
			
		||||
 | 
			
		||||
        // eslint-disable-next-line no-console
 | 
			
		||||
        console.error('openItem not implemented', item);
 | 
			
		||||
        CoreNavigator.navigateToSitePath('viewer/iframe', { params: { title: item.label, url: item.url } });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -819,7 +819,6 @@ export class CoreQuestionHelperProvider {
 | 
			
		||||
            if (span.innerHTML) {
 | 
			
		||||
                // There's a hidden feedback. Mark the icon as tappable.
 | 
			
		||||
                // The click listener is only added if treatCorrectnessIconsClicks is called.
 | 
			
		||||
                // @todo: Check if another attribute needs to be used now instead of tappable.
 | 
			
		||||
                icon.setAttribute('tappable', '');
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
@ -843,9 +842,7 @@ export class CoreQuestionHelperProvider {
 | 
			
		||||
        contextInstanceId?: number,
 | 
			
		||||
        courseId?: number,
 | 
			
		||||
    ): void {
 | 
			
		||||
 | 
			
		||||
        // @todo: Check if another attribute needs to be used now instead of tappable.
 | 
			
		||||
        const icons = <HTMLElement[]> Array.from(element.querySelectorAll('i.icon.questioncorrectnessicon[tappable]'));
 | 
			
		||||
        const icons = <HTMLElement[]> Array.from(element.querySelectorAll('ion-icon.questioncorrectnessicon[tappable]'));
 | 
			
		||||
        const title = Translate.instant('core.question.feedback');
 | 
			
		||||
 | 
			
		||||
        icons.forEach((icon) => {
 | 
			
		||||
 | 
			
		||||
@ -153,8 +153,6 @@ export class CoreSettingsGeneralPage {
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Called when the analytics setting is enabled or disabled.
 | 
			
		||||
     *
 | 
			
		||||
     * @todo
 | 
			
		||||
     */
 | 
			
		||||
    async analyticsEnabledChanged(): Promise<void> {
 | 
			
		||||
        await CorePushNotifications.enableAnalytics(this.analyticsEnabled);
 | 
			
		||||
 | 
			
		||||
@ -37,7 +37,6 @@ export interface CoreTagAreaHandler extends CoreDelegateHandler {
 | 
			
		||||
     * Get the component to use to display items.
 | 
			
		||||
     *
 | 
			
		||||
     * @return The component (or promise resolved with component) to use, undefined if not found.
 | 
			
		||||
     * @todo, check return types.
 | 
			
		||||
     */
 | 
			
		||||
    getComponent(): Type<unknown> | Promise<Type<unknown>>;
 | 
			
		||||
}
 | 
			
		||||
@ -85,7 +84,6 @@ export class CoreTagAreaDelegateService extends CoreDelegate<CoreTagAreaHandler>
 | 
			
		||||
     * @param component Component name.
 | 
			
		||||
     * @param itemType Item type.
 | 
			
		||||
     * @return The component (or promise resolved with component) to use, undefined if not found.
 | 
			
		||||
     * @todo, check return types.
 | 
			
		||||
     */
 | 
			
		||||
    async getComponent(component: string, itemType: string): Promise<Type<unknown> | undefined> {
 | 
			
		||||
        const type = component + '/' + itemType;
 | 
			
		||||
 | 
			
		||||
@ -35,6 +35,7 @@ import { CoreFileUploaderHelper } from '@features/fileuploader/services/fileuplo
 | 
			
		||||
import { CoreIonLoadingElement } from '@classes/ion-loading';
 | 
			
		||||
import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
import { CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'page-core-user-profile',
 | 
			
		||||
@ -239,8 +240,8 @@ export class CoreUserProfilePage implements OnInit, OnDestroy {
 | 
			
		||||
    async refreshUser(event?: CustomEvent<IonRefresher>): Promise<void> {
 | 
			
		||||
        await CoreUtils.ignoreErrors(Promise.all([
 | 
			
		||||
            CoreUser.invalidateUserCache(this.userId),
 | 
			
		||||
            // @todo this.coursesProvider.invalidateUserNavigationOptions(),
 | 
			
		||||
            // this.coursesProvider.invalidateUserAdministrationOptions()
 | 
			
		||||
            CoreCourses.invalidateUserNavigationOptions(),
 | 
			
		||||
            CoreCourses.invalidateUserAdministrationOptions(),
 | 
			
		||||
        ]));
 | 
			
		||||
 | 
			
		||||
        await this.fetchUser();
 | 
			
		||||
 | 
			
		||||
@ -20,7 +20,8 @@ import { CoreUtils } from '@services/utils/utils';
 | 
			
		||||
import { CoreEvents } from '@singletons/events';
 | 
			
		||||
import { CoreUserProfile } from './user';
 | 
			
		||||
import { makeSingleton } from '@singletons';
 | 
			
		||||
import { CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreCourses, CoreCourseUserAdminOrNavOptionIndexed } from '@features/courses/services/courses';
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Interface that all user profile handlers must implement.
 | 
			
		||||
@ -241,9 +242,22 @@ export class CoreUserDelegateService extends CoreDelegate<CoreUserProfileHandler
 | 
			
		||||
     * @return Promise resolved when done.
 | 
			
		||||
     */
 | 
			
		||||
    protected async calculateUserHandlers(user: CoreUserProfile, courseId?: number): Promise<void> {
 | 
			
		||||
        // @todo: Get Course admin/nav options.
 | 
			
		||||
        let navOptions;
 | 
			
		||||
        let admOptions;
 | 
			
		||||
        let navOptions: CoreCourseUserAdminOrNavOptionIndexed | undefined;
 | 
			
		||||
        let admOptions: CoreCourseUserAdminOrNavOptionIndexed | undefined;
 | 
			
		||||
 | 
			
		||||
        if (CoreCourses.canGetAdminAndNavOptions()) {
 | 
			
		||||
            // Get course options.
 | 
			
		||||
            const courses = await CoreCourses.getUserCourses(true);
 | 
			
		||||
            const courseIds = courses.map((course) => course.id);
 | 
			
		||||
 | 
			
		||||
            const options = await CoreCourses.getCoursesAdminAndNavOptions(courseIds);
 | 
			
		||||
 | 
			
		||||
            // For backwards compatibility we don't modify the courseId.
 | 
			
		||||
            const courseIdForOptions = courseId || CoreSites.getCurrentSiteHomeId();
 | 
			
		||||
 | 
			
		||||
            navOptions = options.navOptions[courseIdForOptions];
 | 
			
		||||
            admOptions = options.admOptions[courseIdForOptions];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const userData = this.userHandlers[user.id];
 | 
			
		||||
        userData.handlers = [];
 | 
			
		||||
 | 
			
		||||
@ -759,7 +759,7 @@ export class CoreUserProvider {
 | 
			
		||||
     * @param siteId Site ID. If not defined, current site.
 | 
			
		||||
     * @return Promise resolved if success.
 | 
			
		||||
     */
 | 
			
		||||
    updateUserPreference(name: string, value: string, userId?: number, siteId?: string): Promise<void> {
 | 
			
		||||
    updateUserPreference(name: string, value: string | undefined, userId?: number, siteId?: string): Promise<void> {
 | 
			
		||||
        const preferences = [
 | 
			
		||||
            {
 | 
			
		||||
                type: name,
 | 
			
		||||
@ -780,7 +780,7 @@ export class CoreUserProvider {
 | 
			
		||||
     * @return Promise resolved if success.
 | 
			
		||||
     */
 | 
			
		||||
    async updateUserPreferences(
 | 
			
		||||
        preferences: { type: string; value: string }[],
 | 
			
		||||
        preferences: { type: string; value: string | undefined }[],
 | 
			
		||||
        disableNotifications?: boolean,
 | 
			
		||||
        userId?: number,
 | 
			
		||||
        siteId?: string,
 | 
			
		||||
 | 
			
		||||
@ -15,16 +15,19 @@
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreViewerImageComponent } from './image/image';
 | 
			
		||||
import { CoreViewerTextComponent } from './text/text';
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreViewerImageComponent,
 | 
			
		||||
        CoreViewerTextComponent,
 | 
			
		||||
    ],
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [
 | 
			
		||||
        CoreViewerImageComponent,
 | 
			
		||||
        CoreViewerTextComponent,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										14
									
								
								src/core/features/viewer/components/image/image.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/core/features/viewer/components/image/image.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,14 @@
 | 
			
		||||
<ion-header>
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
        <ion-title>{{ title }}</ion-title>
 | 
			
		||||
        <ion-buttons slot="end">
 | 
			
		||||
            <ion-button (click)="closeModal()" [attr.aria-label]="'core.close' | translate">
 | 
			
		||||
                <ion-icon name="fas-times" slot="icon-only"></ion-icon>
 | 
			
		||||
            </ion-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<!-- @todo: zoom="true" maxZoom="2" class="core-zoom-pane". Now we need to use ionSlider? -->
 | 
			
		||||
<ion-content [scrollX]="true" [scrollY]="true">
 | 
			
		||||
    <img [src]="image" [alt]="title" core-external-content [component]="component" [componentId]="componentId">
 | 
			
		||||
</ion-content>
 | 
			
		||||
							
								
								
									
										9
									
								
								src/core/features/viewer/components/image/image.scss
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/core/features/viewer/components/image/image.scss
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,9 @@
 | 
			
		||||
:host {
 | 
			
		||||
    .core-zoom-pane {
 | 
			
		||||
        height: 100%;
 | 
			
		||||
 | 
			
		||||
        img {
 | 
			
		||||
            max-width: none;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										44
									
								
								src/core/features/viewer/components/image/image.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/core/features/viewer/components/image/image.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,44 @@
 | 
			
		||||
// (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 { Component, Input, OnInit } from '@angular/core';
 | 
			
		||||
 | 
			
		||||
import { ModalController, Translate } from '@singletons';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Modal component to view an image.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-viewer-image',
 | 
			
		||||
    templateUrl: 'image.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreViewerImageComponent implements OnInit {
 | 
			
		||||
 | 
			
		||||
    @Input() title?: string; // Modal title.
 | 
			
		||||
    @Input() image?: string; // Image URL.
 | 
			
		||||
    @Input() component?: string; // Component to use in external-content.
 | 
			
		||||
    @Input() componentId?: string | number; // Component ID to use in external-content.
 | 
			
		||||
 | 
			
		||||
    ngOnInit(): void {
 | 
			
		||||
        this.title = this.title || Translate.instant('core.imageviewer');
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Close modal.
 | 
			
		||||
     */
 | 
			
		||||
    closeModal(): void {
 | 
			
		||||
        ModalController.dismiss();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								src/core/features/viewer/pages/iframe/iframe.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/core/features/viewer/pages/iframe/iframe.html
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,13 @@
 | 
			
		||||
<ion-header>
 | 
			
		||||
    <ion-toolbar>
 | 
			
		||||
        <ion-buttons slot="start">
 | 
			
		||||
            <ion-back-button [attr.aria-label]="'core.back' | translate"></ion-back-button>
 | 
			
		||||
        </ion-buttons>
 | 
			
		||||
        <ion-title>{{ title }}</ion-title>
 | 
			
		||||
    </ion-toolbar>
 | 
			
		||||
</ion-header>
 | 
			
		||||
<ion-content>
 | 
			
		||||
    <core-loading [hideUntil]="finalUrl">
 | 
			
		||||
        <core-iframe *ngIf="finalUrl" [src]="finalUrl"></core-iframe>
 | 
			
		||||
    </core-loading>
 | 
			
		||||
</ion-content>
 | 
			
		||||
							
								
								
									
										38
									
								
								src/core/features/viewer/pages/iframe/iframe.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/core/features/viewer/pages/iframe/iframe.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,38 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreSharedModule } from '@/core/shared.module';
 | 
			
		||||
import { CoreViewerIframePage } from './iframe';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: '',
 | 
			
		||||
        component: CoreViewerIframePage,
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        RouterModule.forChild(routes),
 | 
			
		||||
        CoreSharedModule,
 | 
			
		||||
    ],
 | 
			
		||||
    declarations: [
 | 
			
		||||
        CoreViewerIframePage,
 | 
			
		||||
    ],
 | 
			
		||||
    exports: [RouterModule],
 | 
			
		||||
})
 | 
			
		||||
export class CoreViewerIframePageModule {}
 | 
			
		||||
							
								
								
									
										57
									
								
								src/core/features/viewer/pages/iframe/iframe.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/core/features/viewer/pages/iframe/iframe.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,57 @@
 | 
			
		||||
// (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 { Component, OnInit } from '@angular/core';
 | 
			
		||||
import { CoreNavigator } from '@services/navigator';
 | 
			
		||||
 | 
			
		||||
import { CoreSites } from '@services/sites';
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Page to display a URL in an iframe.
 | 
			
		||||
 */
 | 
			
		||||
@Component({
 | 
			
		||||
    selector: 'core-viewer-iframe',
 | 
			
		||||
    templateUrl: 'iframe.html',
 | 
			
		||||
})
 | 
			
		||||
export class CoreViewerIframePage implements OnInit {
 | 
			
		||||
 | 
			
		||||
    title?: string; // Page title.
 | 
			
		||||
    url?: string; // Iframe URL.
 | 
			
		||||
    /* Whether the URL should be open with auto-login. Accepts the following values:
 | 
			
		||||
        "yes" -> Always auto-login.
 | 
			
		||||
        "no" -> Never auto-login.
 | 
			
		||||
        "check" -> Auto-login only if it points to the current site. Default value. */
 | 
			
		||||
    autoLogin?: string;
 | 
			
		||||
    finalUrl?: string;
 | 
			
		||||
 | 
			
		||||
    async ngOnInit(): Promise<void> {
 | 
			
		||||
        this.title = CoreNavigator.getRouteParam('title');
 | 
			
		||||
        this.url = CoreNavigator.getRouteParam('url');
 | 
			
		||||
        this.autoLogin = CoreNavigator.getRouteParam('autoLogin') || 'check';
 | 
			
		||||
 | 
			
		||||
        if (!this.url) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const currentSite = CoreSites.getCurrentSite();
 | 
			
		||||
 | 
			
		||||
        if (currentSite && (this.autoLogin == 'yes' || (this.autoLogin == 'check' && currentSite.containsUrl(this.url)))) {
 | 
			
		||||
            // Format the URL to add auto-login.
 | 
			
		||||
            this.finalUrl = await currentSite.getAutoLoginUrl(this.url, false);
 | 
			
		||||
        } else {
 | 
			
		||||
            this.finalUrl = this.url;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										28
									
								
								src/core/features/viewer/viewer-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/core/features/viewer/viewer-lazy.module.ts
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
// (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 { NgModule } from '@angular/core';
 | 
			
		||||
import { RouterModule, Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'iframe',
 | 
			
		||||
        loadChildren: () => import('./pages/iframe/iframe.module').then( m => m.CoreViewerIframePageModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [RouterModule.forChild(routes)],
 | 
			
		||||
})
 | 
			
		||||
export class CoreViewerLazyModule {}
 | 
			
		||||
@ -13,11 +13,21 @@
 | 
			
		||||
// limitations under the License.
 | 
			
		||||
 | 
			
		||||
import { NgModule } from '@angular/core';
 | 
			
		||||
import { Routes } from '@angular/router';
 | 
			
		||||
 | 
			
		||||
import { CoreMainMenuTabRoutingModule } from '@features/mainmenu/mainmenu-tab-routing.module';
 | 
			
		||||
import { CoreViewerComponentsModule } from './components/components.module';
 | 
			
		||||
 | 
			
		||||
const routes: Routes = [
 | 
			
		||||
    {
 | 
			
		||||
        path: 'viewer',
 | 
			
		||||
        loadChildren: () => import('./viewer-lazy.module').then(m => m.CoreViewerLazyModule),
 | 
			
		||||
    },
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
@NgModule({
 | 
			
		||||
    imports: [
 | 
			
		||||
        CoreMainMenuTabRoutingModule.forChild(routes),
 | 
			
		||||
        CoreViewerComponentsModule,
 | 
			
		||||
    ],
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
@ -19,6 +19,7 @@ import { CoreSite, CoreSiteWSPreSets } from '@classes/site';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { makeSingleton, Translate } from '@singletons';
 | 
			
		||||
import { CoreWSExternalWarning } from '@services/ws';
 | 
			
		||||
import { CoreCourses } from '@features/courses/services/courses';
 | 
			
		||||
 | 
			
		||||
const ROOT_CACHE_KEY = 'mmGroups:';
 | 
			
		||||
 | 
			
		||||
@ -242,8 +243,11 @@ export class CoreGroupsProvider {
 | 
			
		||||
            return this.getUserGroupsInCourse(0, siteId);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // @todo Get courses.
 | 
			
		||||
        return <CoreGroup[]>[];
 | 
			
		||||
        const courses = <CoreCourseBase[]> await CoreCourses.getUserCourses(false, siteId);
 | 
			
		||||
 | 
			
		||||
        courses.push({ id: site.getSiteHomeId() }); // Add site home.
 | 
			
		||||
 | 
			
		||||
        return this.getUserGroups(courses, siteId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
@ -18,6 +18,7 @@ import { CoreConfig } from '@services/config';
 | 
			
		||||
import { CoreConstants } from '@/core/constants';
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
import { makeSingleton } from '@singletons';
 | 
			
		||||
import { CoreH5P } from '@features/h5p/services/h5p';
 | 
			
		||||
 | 
			
		||||
const VERSION_APPLIED = 'version_applied';
 | 
			
		||||
 | 
			
		||||
@ -42,13 +43,13 @@ export class CoreUpdateManagerProvider {
 | 
			
		||||
     * @return Promise resolved when the update process finishes.
 | 
			
		||||
     */
 | 
			
		||||
    async load(): Promise<void> {
 | 
			
		||||
        const promises = [];
 | 
			
		||||
        const promises: Promise<unknown>[] = [];
 | 
			
		||||
        const versionCode = CoreConstants.CONFIG.versioncode;
 | 
			
		||||
 | 
			
		||||
        const versionApplied = await CoreConfig.get<number>(VERSION_APPLIED, 0);
 | 
			
		||||
 | 
			
		||||
        if (versionCode >= 3900 && versionApplied < 3900 && versionApplied > 0) {
 | 
			
		||||
            // @todo: H5P update.
 | 
			
		||||
            promises.push(CoreH5P.h5pPlayer.deleteAllContentIndexes());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        try {
 | 
			
		||||
 | 
			
		||||
@ -31,11 +31,20 @@ import { CoreIonLoadingElement } from '@classes/ion-loading';
 | 
			
		||||
import { CoreCanceledError } from '@classes/errors/cancelederror';
 | 
			
		||||
import { CoreError } from '@classes/errors/error';
 | 
			
		||||
import { CoreSilentError } from '@classes/errors/silenterror';
 | 
			
		||||
 | 
			
		||||
import { makeSingleton, Translate, AlertController, LoadingController, ToastController } from '@singletons';
 | 
			
		||||
import {
 | 
			
		||||
    makeSingleton,
 | 
			
		||||
    Translate,
 | 
			
		||||
    AlertController,
 | 
			
		||||
    LoadingController,
 | 
			
		||||
    ToastController,
 | 
			
		||||
    PopoverController,
 | 
			
		||||
    ModalController,
 | 
			
		||||
} from '@singletons';
 | 
			
		||||
import { CoreLogger } from '@singletons/logger';
 | 
			
		||||
import { CoreFileSizeSum } from '@services/plugin-file-delegate';
 | 
			
		||||
import { CoreNetworkError } from '@classes/errors/network-error';
 | 
			
		||||
import { CoreBSTooltipComponent } from '@components/bs-tooltip/bs-tooltip';
 | 
			
		||||
import { CoreViewerImageComponent } from '@features/viewer/components/image/image';
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * "Utils" service with helper functions for UI, DOM elements and HTML code.
 | 
			
		||||
@ -810,8 +819,18 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
            el.setAttribute('data-original-title', content);
 | 
			
		||||
            el.setAttribute('title', '');
 | 
			
		||||
 | 
			
		||||
            el.addEventListener('click', () => {
 | 
			
		||||
                // @todo
 | 
			
		||||
            el.addEventListener('click', async (ev: Event) => {
 | 
			
		||||
                const html = el.getAttribute('data-html');
 | 
			
		||||
 | 
			
		||||
                const popover = await PopoverController.create({
 | 
			
		||||
                    component: CoreBSTooltipComponent,
 | 
			
		||||
                    componentProps: {
 | 
			
		||||
                        content,
 | 
			
		||||
                        html: html === 'true',
 | 
			
		||||
                    },
 | 
			
		||||
                    event: ev,
 | 
			
		||||
                });
 | 
			
		||||
                await popover.present();
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
@ -1554,12 +1573,32 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
     * @param message Modal message.
 | 
			
		||||
     * @param buttons Buttons to pass to the modal.
 | 
			
		||||
     * @param placeholder Placeholder of the input element if any.
 | 
			
		||||
     * @return Promise resolved when modal presented.
 | 
			
		||||
     * @return Promise resolved with the entered text if any.
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    showTextareaPrompt(title: string, message: string, buttons: (string | unknown)[], placeholder?: string): Promise<unknown> {
 | 
			
		||||
        // @todo
 | 
			
		||||
        return Promise.resolve();
 | 
			
		||||
    async showTextareaPrompt(
 | 
			
		||||
        title: string,
 | 
			
		||||
        message: string,
 | 
			
		||||
        buttons: AlertButton[],
 | 
			
		||||
        placeholder?: string,
 | 
			
		||||
    ): Promise<string | undefined> {
 | 
			
		||||
        const alert = await AlertController.create({
 | 
			
		||||
            header: title,
 | 
			
		||||
            message,
 | 
			
		||||
            inputs: [
 | 
			
		||||
                {
 | 
			
		||||
                    name: 'textarea-prompt',
 | 
			
		||||
                    type: 'textarea',
 | 
			
		||||
                    placeholder: placeholder,
 | 
			
		||||
                },
 | 
			
		||||
            ],
 | 
			
		||||
            buttons,
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        await alert.present();
 | 
			
		||||
 | 
			
		||||
        const result = await alert.onWillDismiss();
 | 
			
		||||
 | 
			
		||||
        return result.data?.values?.['textarea-prompt'];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
@ -1671,9 +1710,30 @@ export class CoreDomUtilsProvider {
 | 
			
		||||
     * @param componentId An ID to use in conjunction with the component.
 | 
			
		||||
     * @param fullScreen Whether the modal should be full screen.
 | 
			
		||||
     */
 | 
			
		||||
    // eslint-disable-next-line @typescript-eslint/no-unused-vars
 | 
			
		||||
    viewImage(image: string, title?: string | null, component?: string, componentId?: string | number, fullScreen?: boolean): void {
 | 
			
		||||
        // @todo
 | 
			
		||||
    async viewImage(
 | 
			
		||||
        image: string,
 | 
			
		||||
        title?: string | null,
 | 
			
		||||
        component?: string,
 | 
			
		||||
        componentId?: string | number,
 | 
			
		||||
        fullScreen?: boolean,
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
        if (!image) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        const modal = await ModalController.create({
 | 
			
		||||
            component: CoreViewerImageComponent,
 | 
			
		||||
            componentProps: {
 | 
			
		||||
                title,
 | 
			
		||||
                image,
 | 
			
		||||
                component,
 | 
			
		||||
                componentId,
 | 
			
		||||
            },
 | 
			
		||||
            cssClass: fullScreen ? 'core-modal-fullscreen' : '',
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        await modal.present();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user