MOBILE-4193 grades: Avoid filtering rich images

main
Noel De Martin 2023-03-14 18:20:11 +01:00
parent 0c998b8f8b
commit f82d3504f6
8 changed files with 68 additions and 10 deletions

View File

@ -22,6 +22,7 @@ import { AddonModLtiHelper } from '../lti-helper';
import { AddonModLtiIndexComponent } from '../../components/index';
import { CoreModuleHandlerBase } from '@features/course/classes/module-base-handler';
import { CoreCourse } from '@features/course/services/course';
import { CoreSites } from '@services/sites';
/**
* Handler to support LTI modules.
@ -86,6 +87,19 @@ export class AddonModLtiModuleHandlerService extends CoreModuleHandlerBase imple
return module?.modicon ?? modicon ?? CoreCourse.getModuleIconSrc(this.modName);
}
/**
* @inheritdoc
*/
iconIsShape(module?: CoreCourseModuleData | undefined, modicon?: string | undefined): boolean | undefined {
const iconUrl = module?.modicon ?? modicon;
if (!iconUrl) {
return true;
}
return iconUrl.startsWith(CoreSites.getRequiredCurrentSite().siteUrl);
}
}
export const AddonModLtiModuleHandler = makeSingleton(AddonModLtiModuleHandlerService);

View File

@ -1,5 +1,5 @@
<img *ngIf="!isLocalUrl" [src]="icon" [alt]="showAlt ? modNameTranslated : ''" [attr.role]="!showAlt ? 'presentation' : null"
class="core-module-icon" core-external-content [component]="linkIconWithComponent ? modname : null"
class="core-module-icon" [class.no-filter]="noFilter" core-external-content [component]="linkIconWithComponent ? modname : null"
[componentId]="linkIconWithComponent ? componentId : null" (error)="loadFallbackIcon()">
<img *ngIf="isLocalUrl" [src]="icon" [alt]="showAlt ? modNameTranslated : ''" [attr.role]="!showAlt ? 'presentation' : null"
class="core-module-icon" (error)="loadFallbackIcon()">
class="core-module-icon" [class.no-filter]="noFilter" (error)="loadFallbackIcon()">

View File

@ -42,6 +42,11 @@ img {
white-space: nowrap;
overflow: hidden;
}
&.no-filter {
--filter: none;
}
}
:host-context(ion-item) {

View File

@ -13,7 +13,7 @@
// limitations under the License.
import { CoreConstants, ModPurpose } from '@/core/constants';
import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChange } from '@angular/core';
import { Component, ElementRef, EventEmitter, Input, OnChanges, OnInit, Output, SimpleChange } from '@angular/core';
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
import { CoreSites } from '@services/sites';
@ -34,9 +34,12 @@ export class CoreModIconComponent implements OnInit, OnChanges {
@Input() modname?: string; // The module name. Used also as component if set.
@Input() componentId?: number; // Component Id for external icons.
@Input() modicon?: string; // Module icon url or local url.
@Input() noFilter?: boolean; // Whether to disable filters.
@Input() showAlt = true; // Show alt otherwise it's only presentation icon.
@Input() purpose: ModPurpose = ModPurpose.MOD_PURPOSE_OTHER; // Purpose of the module.
@Output() failedLoading = new EventEmitter<void>();
icon = '';
modNameTranslated = '';
isLocalUrl = true;
@ -122,6 +125,8 @@ export class CoreModIconComponent implements OnInit, OnChanges {
}
this.icon = path + moduleName + '.svg';
this.failedLoading.emit();
}
}

View File

@ -87,6 +87,15 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
*/
getIconSrc?(module?: CoreCourseModuleData, modicon?: string): Promise<string | undefined> | string | undefined;
/**
* Check whether the icon should be treated as a shape or a rich image.
*
* @param module Module to get the icon from.
* @param modicon The mod icon string.
* @returns Whether the icon should be treated as a shape.
*/
iconIsShape?(module?: CoreCourseModuleData, modicon?: string): Promise<boolean | undefined> | boolean | undefined;
/**
* Check if this type of module supports a certain feature.
* If this function is implemented, the supportedFeatures object will be ignored.
@ -396,6 +405,18 @@ export class CoreCourseModuleDelegateService extends CoreDelegate<CoreCourseModu
return icon ?? CoreCourse.getModuleIconSrc(modname, modicon) ?? '';
}
/**
* Get whether the icon for the given module should be treated as a shape or a rich image.
*
* @param modname The name of the module type.
* @param modicon The mod icon string.
* @param module The module to use.
* @returns Whether the icon should be treated as a shape.
*/
async moduleIconIsShape(modname: string, modicon?: string, module?: CoreCourseModuleData): Promise<boolean | undefined> {
return await this.executeFunctionOnEnabled<Promise<boolean>>(modname, 'iconIsShape', [module, modicon]);
}
/**
* Check if a certain type of module supports a certain feature.
*

View File

@ -48,7 +48,8 @@
<img *ngIf="row.image && !row.itemmodule" [src]="row.image" slot="start" class="core-module-icon"
[alt]="row.iconAlt" />
<core-mod-icon *ngIf="row.image && row.itemmodule" [modicon]="row.image" slot="start"
[modname]="row.itemmodule">
[modname]="row.itemmodule" [noFilter]="row.imageIsShape === false"
(failedLoading)="failedLoadingRowImage(row)">
</core-mod-icon>
<span [innerHTML]="row.gradeitem"></span>
</th>

View File

@ -239,4 +239,13 @@ export class CoreGradesCoursePage implements AfterViewInit, OnDestroy {
infiniteComplete && infiniteComplete();
}
/**
* Handle row image failed loading.
*
* @param row Row data.
*/
failedLoadingRowImage(row: CoreGradesFormattedTableRow): void {
delete row.imageIsShape;
}
}

View File

@ -684,14 +684,16 @@ export class CoreGradesHelperProvider {
row.iconAlt = Translate.instant('core.grades.calculatedgrade');
} else if (text.indexOf('/mod/') > -1) {
const module = text.match(/mod\/([^/]*)\//);
if (module?.[1] !== undefined) {
const modname = module?.[1];
if (modname !== undefined) {
const modicon = CoreDomUtils.convertToElement(text).querySelector('img')?.getAttribute('src') ?? undefined;
row.itemtype = 'mod';
row.itemmodule = module[1];
row.itemmodule = modname;
row.iconAlt = CoreCourse.translateModuleName(row.itemmodule) || '';
row.image = await CoreCourseModuleDelegate.getModuleIconSrc(
module[1],
CoreDomUtils.convertToElement(text).querySelector('img')?.getAttribute('src') ?? undefined,
);
row.image = await CoreCourseModuleDelegate.getModuleIconSrc(modname, modicon);
row.imageIsShape = await CoreCourseModuleDelegate.moduleIconIsShape(modname, modicon);
}
} else {
if (row.rowspan && row.rowspan > 1) {
@ -804,6 +806,7 @@ export type CoreGradesFormattedRowCommonData = {
rowclass?: string;
itemtype?: string;
image?: string;
imageIsShape?: boolean;
itemmodule?: string;
iconAlt?: string;
rowspan?: number;