Skip to content

Commit

Permalink
Merge pull request #3838 from crazyserver/MOBILE-4362
Browse files Browse the repository at this point in the history
Mobile 4362
  • Loading branch information
dpalou authored Oct 26, 2023
2 parents 38f4dcd + 1497204 commit 93a9d19
Show file tree
Hide file tree
Showing 24 changed files with 148 additions and 110 deletions.
Original file line number Diff line number Diff line change
@@ -1,13 +1,7 @@
:host {
--mod-icon-filter: brightness(0);

core-mod-icon {
background: transparent;
margin: 0;
--filter: var(--mod-icon-filter);
--filter: var(--module-icon-filter);
}
}

:host-context(html.dark) {
--mod-icon-filter: brightness(0) invert(1);
}
2 changes: 1 addition & 1 deletion src/addons/messages/pages/discussion/discussion.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
<ion-title>
<h1>
<img *ngIf="loaded && !otherMember && conversationImage" class="core-bar-button-image" [src]="conversationImage" alt=""
onError="this.src='assets/img/group-avatar.svg'" core-external-content role="presentation" [siteId]="siteId || null">
onError="this.src='assets/img/group-avatar.svg'" core-external-content role="presentation" [siteId]="siteId">
<core-user-avatar *ngIf="loaded && otherMember" class="core-bar-button-image" [user]="otherMember" [linkProfile]="false"
[checkOnline]="otherMember.showonlinestatus">
</core-user-avatar>
Expand Down
2 changes: 1 addition & 1 deletion src/addons/messages/pages/discussion/discussion.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,6 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
@ViewChild(IonContent) content?: IonContent;
@ViewChild(CoreInfiniteLoadingComponent) infinite?: CoreInfiniteLoadingComponent;

siteId: string;
protected fetching = false;
protected polling?: number;
protected logger: CoreLogger;
Expand All @@ -79,6 +78,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView
conversation?: AddonMessagesConversationFormatted; // The conversation object (if it exists).
userId?: number; // User ID you're talking to (only if group messaging not enabled or it's a new individual conversation).
currentUserId: number;
siteId: string;
title?: string;
showInfo = false;
conversationImage?: string;
Expand Down
14 changes: 0 additions & 14 deletions src/addons/mod/lti/services/handlers/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ 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.
Expand Down Expand Up @@ -87,19 +86,6 @@ 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);
9 changes: 0 additions & 9 deletions src/addons/mod/resource/services/handlers/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -170,14 +170,5 @@ export class AddonModResourceModuleHandlerService extends CoreModuleHandlerBase
return AddonModResourceIndexComponent;
}

/**
* @inheritdoc
*/
iconIsShape(module?: CoreCourseModuleData | undefined, modicon?: string | undefined): boolean | undefined {
const iconUrl = module?.modicon ?? modicon;

return !iconUrl?.startsWith('assets/img/files_legacy/') && !iconUrl?.endsWith('.png');
}

}
export const AddonModResourceModuleHandler = makeSingleton(AddonModResourceModuleHandlerService);
9 changes: 0 additions & 9 deletions src/addons/mod/url/services/handlers/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -218,15 +218,6 @@ export class AddonModUrlModuleHandlerService extends CoreModuleHandlerBase imple
return this.shouldOpenLink(module);
}

/**
* @inheritdoc
*/
iconIsShape(module?: CoreCourseModuleData | undefined, modicon?: string | undefined): boolean | undefined {
const iconUrl = module?.modicon ?? modicon;

return !iconUrl?.startsWith('assets/img/files_legacy/') && !iconUrl?.endsWith('.png');
}

/**
* Log module viewed.
*/
Expand Down
3 changes: 1 addition & 2 deletions src/core/components/mod-icon/mod-icon.scss
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
--icon-radius: var(--module-icon-radius, var(--radius-xs));
--margin-end: 0px;
--margin-vertical: 0px;
--filter: brightness(0) invert(1);

margin-top: var(--margin-vertical);
margin-bottom: var(--margin-vertical);
Expand All @@ -22,7 +21,7 @@
&.#{$type} {
background-color: var(--activity#{$type});
img {
filter: var(--filter);
filter: var(--filter, brightness(0) invert(1));
}
}
}
Expand Down
85 changes: 74 additions & 11 deletions src/core/components/mod-icon/mod-icon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import { Component, ElementRef, Input, OnChanges, OnInit, SimpleChange } from '@
import { CoreCourse } from '@features/course/services/course';
import { CoreCourseModuleDelegate } from '@features/course/services/module-delegate';
import { CoreSites } from '@services/sites';
import { CoreUrlUtils } from '@services/utils/url';

const assetsPath = 'assets/img/';
const fallbackModName = 'external-tool';
Expand Down Expand Up @@ -54,12 +55,7 @@ export class CoreModIconComponent implements OnInit, OnChanges {
async ngOnInit(): Promise<void> {
if (!this.modname && this.modicon) {
// Guess module from the icon url.
const matches = this.modicon.match('/theme/image.php/[^/]+/([^/]+)/[-0-9]*/');
this.modname = (matches && matches[1]) || '';

if (this.modname.startsWith('mod_')) {
this.modname = this.modname.substring(4);
}
this.modname = this.getComponentNameFromIconUrl(this.modicon);
}

this.modNameTranslated = CoreCourse.translateModuleName(this.modname, this.fallbackTranslation);
Expand Down Expand Up @@ -105,16 +101,15 @@ export class CoreModIconComponent implements OnInit, OnChanges {
!!this.modname &&
!!this.componentId &&
!this.isLocalUrl &&
!this.icon.match('/theme/image.php/[^/]+/' + this.modname + '/[-0-9]*/');
this.getComponentNameFromIconUrl(this.icon) != this.modname;

const iconIsShape = await CoreCourseModuleDelegate.moduleIconIsShape(this.modname, this.icon);
this.noFilter = iconIsShape === false;
this.noFilter = await this.getIconNoFilter();
}

/**
* Icon to load on error.
*/
loadFallbackIcon(): void {
async loadFallbackIcon(): Promise<void> {
this.isLocalUrl = true;
const moduleName = !this.modname || CoreCourse.CORE_MODULES.indexOf(this.modname) < 0
? fallbackModName
Expand All @@ -127,7 +122,75 @@ export class CoreModIconComponent implements OnInit, OnChanges {
}

this.icon = path + moduleName + '.svg';
this.noFilter = false;
this.noFilter = await this.getIconNoFilter();
}

/**
* Returns if the icon does not need to be filtered.
*
* @returns wether the icon does not need to be filtered.
*/
protected async getIconNoFilter(): Promise<boolean> {
// Earlier 4.0, icons were never filtered.
if (this.legacyIcon) {
return true;
}

// No icon or local icon (not legacy), filter it.
if (!this.icon || this.isLocalUrl) {
return false;
}

// If it's an Moodle Theme icon, check if filtericon is set and use it.
if (this.icon && CoreUrlUtils.isThemeImageUrl(this.icon)) {
const iconParams = CoreUrlUtils.extractUrlParams(this.icon);
if (iconParams['filtericon'] === '1') {
return false;
}

// filtericon was introduced in 4.2 and backported to 4.1.3 and 4.0.8.
if (this.modname && !CoreSites.getCurrentSite()?.isVersionGreaterEqualThan(['4.0.8', '4.1.3', '4.2'])) {
// If version is prior to that, check if the url is a module icon and filter it.
if (this.getComponentNameFromIconUrl(this.icon) === this.modname) {
return false;
}
}
}

// External icons, or non monologo, do not filter.
return true;
}

/**
* Guesses the mod name form the url.
*
* @param iconUrl Icon url.
* @returns Guessed modname.
*/
protected getComponentNameFromIconUrl(iconUrl: string): string {
if (!CoreUrlUtils.isThemeImageUrl(this.icon)) {
// Cannot be guessed.
return '';
}

const iconParams = CoreUrlUtils.extractUrlParams(iconUrl);
let component = iconParams['component'];

if (!component) {
const matches = iconUrl.match('/theme/image.php/[^/]+/([^/]+)/[-0-9]*/');
component = (matches && matches[1]) || '';
}

// Some invalid components (others may be added later on).
if (component === 'core' || component === 'theme') {
return '';
}

if (component.startsWith('mod_')) {
component = component.substring(4);
}

return component;
}

}
11 changes: 6 additions & 5 deletions src/core/components/user-avatar/core-user-avatar.html
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
<ng-container *ngIf="avatarUrl">
<img *ngIf="linkProfile" [src]="avatarUrl" [alt]="'core.pictureof' | translate:{$a: fullname}" core-external-content
<img class="userpicture" *ngIf="linkProfile" [src]="avatarUrl" [alt]="'core.pictureof' | translate:{$a: fullname}" core-external-content
(error)="loadImageError()" (ariaButtonClick)="gotoProfile($event)" [siteId]="siteId">

<img *ngIf="!linkProfile" [src]="avatarUrl" [alt]="'core.pictureof' | translate:{$a: fullname}" core-external-content
(error)="loadImageError()" aria-hidden="true" [siteId]="siteId">
<img class="userpicture" *ngIf="!linkProfile" [src]="avatarUrl" [alt]="'core.pictureof' | translate:{$a: fullname}"
core-external-content (error)="loadImageError()" aria-hidden="true" [siteId]="siteId">
</ng-container>
<ng-container *ngIf="!avatarUrl && initials">
<div class="userinitials" *ngIf="linkProfile" [attr.aria-label]="'core.pictureof' | translate:{$a: fullname}"
Expand All @@ -16,10 +16,11 @@
</div>
</ng-container>
<ng-container *ngIf="!avatarUrl && !initials">
<img *ngIf="linkProfile" src="assets/img/user-avatar.png" [alt]="'core.pictureof' | translate:{$a: fullname}"
<img class="userpicture" *ngIf="linkProfile" src="assets/img/user-avatar.png" [alt]="'core.pictureof' | translate:{$a: fullname}"
(ariaButtonClick)="gotoProfile($event)">

<img *ngIf="!linkProfile" src="assets/img/user-avatar.png" [alt]="'core.pictureof' | translate:{$a: fullname}" aria-hidden="true">
<img class="userpicture" *ngIf="!linkProfile" src="assets/img/user-avatar.png" [alt]="'core.pictureof' | translate:{$a: fullname}"
aria-hidden="true">
</ng-container>

<span *ngIf="checkOnline && isOnline()" class="contact-status online" role="status" [attr.aria-label]="'core.online' | translate">
Expand Down
58 changes: 33 additions & 25 deletions src/core/components/user-avatar/user-avatar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,40 +4,47 @@
position: relative;
width: var(--core-avatar-size);
height: var(--core-avatar-size);
padding: 0px;
--contact-status-size: 14px;
--margin-end-on-item: 8px;
--margin-vertical-on-item: 8px;
--userpicture-padding: 0px;

img {
img.userpicture {
border-radius: var(--core-avatar-radius);
width: var(--core-avatar-size);
height: var(--core-avatar-size);
max-width: var(--core-avatar-size);
max-height: var(--core-avatar-size);
}
img[alt] {
text-indent: -999999px;
white-space: nowrap;
overflow: hidden;
}
img[core-external-content]:not([src]),
img[core-external-content][src=""] {
visibility: visible;
display: inline-block;
position: relative;
&:after {
border-radius: var(--core-avatar-radius);
display: block;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: url('/assets/img/user-avatar.png');
background-size: contain;
content: "";
padding: var(--userpicture-padding);
&[alt] {
text-indent: -999999px;
white-space: nowrap;
overflow: hidden;
}
&:not([src]),
&[src=""] {
visibility: visible;
display: inline-block;
position: relative;
margin: var(--userpicture-padding);
width: calc(var(--core-avatar-size) - var(--userpicture-padding) - var(--userpicture-padding));
height: calc(var(--core-avatar-size) - var(--userpicture-padding) - var(--userpicture-padding));
&:after {
border-radius: var(--core-avatar-radius);
display: block;
position: absolute;
top: 0;
left: 0;
right: 0;
bottom: 0;
background: url('/assets/img/user-avatar.png');
background-size: contain;
content: "";
}
}
}

&.core-bar-button-image {
padding: 0;
width: var(--core-header-toolbar-button-image-size);
Expand Down Expand Up @@ -74,9 +81,10 @@
border-radius: var(--core-avatar-radius);
color: var(--gray-800);
font-weight: normal;
width: var(--core-avatar-size);
height: var(--core-avatar-size);
width: calc(var(--core-avatar-size) - var(--userpicture-padding) - var(--userpicture-padding));
height: calc(var(--core-avatar-size) - var(--userpicture-padding) - var(--userpicture-padding));
font-size: calc(var(--core-avatar-size)*0.3);
margin: var(--userpicture-padding);
}

&.large-avatar .userinitials {
Expand Down
8 changes: 4 additions & 4 deletions src/core/components/user-avatar/user-avatar.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,8 @@ import { CoreEventObserver, CoreEvents } from '@singletons/events';
import { USER_PROFILE_PICTURE_UPDATED, CoreUserBasicData } from '@features/user/services/user';
import { CoreNavigator } from '@services/navigator';
import { CoreNetwork } from '@services/network';
import { CoreUrl } from '@singletons/url';
import { CoreUserHelper } from '@features/user/services/user-helper';
import { CoreUrlUtils } from '@services/utils/url';

/**
* Component to display a "user avatar".
Expand Down Expand Up @@ -78,7 +78,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy {
}

/**
* Listen to changes.
* @inheritdoc
*/
ngOnChanges(changes: { [name: string]: SimpleChange }): void {
// If something change, update the fields.
Expand Down Expand Up @@ -111,7 +111,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy {
this.initials = CoreUserHelper.getUserInitials(this.user);
}

if (this.initials && this.avatarUrl && CoreUrl.parse(this.avatarUrl)?.path?.startsWith('/theme/image.php')) {
if (this.initials && this.avatarUrl && CoreUrlUtils.isThemeImageUrl(this.avatarUrl)) {
this.avatarUrl = undefined;
}

Expand Down Expand Up @@ -166,7 +166,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy {
}

/**
* Component destroyed.
* @inheritdoc
*/
ngOnDestroy(): void {
this.pictureObserver.off();
Expand Down
2 changes: 2 additions & 0 deletions src/core/features/course/services/module-delegate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ export interface CoreCourseModuleHandler extends CoreDelegateHandler {
* @param module Module to get the icon from.
* @param modicon The mod icon string.
* @returns Whether the icon should be treated as a shape.
* @deprecated since 4.3. Now it uses platform information. This function is not used anymore.
*/
iconIsShape?(module?: CoreCourseModuleData, modicon?: string): Promise<boolean | undefined> | boolean | undefined;

Expand Down Expand Up @@ -415,6 +416,7 @@ export class CoreCourseModuleDelegateService extends CoreDelegate<CoreCourseModu
* @param modicon The mod icon string.
* @param module The module to use.
* @returns Whether the icon should be treated as a shape.
* @deprecated since 4.3. Now it uses platform information. This function is not used anymore.
*/
async moduleIconIsShape(modname: string, modicon?: string, module?: CoreCourseModuleData): Promise<boolean | undefined> {
return await this.executeFunctionOnEnabled<Promise<boolean>>(modname, 'iconIsShape', [module, modicon]);
Expand Down
Loading

0 comments on commit 93a9d19

Please sign in to comment.