MOBILE-3833 notifications: Update styles

main
Pau Ferrer Ocaña 2022-03-28 11:59:38 +02:00
parent 6255c86708
commit c64f0b9353
5 changed files with 188 additions and 115 deletions

View File

@ -17,20 +17,11 @@
</ion-refresher>
<core-loading [hideUntil]="notificationsLoaded">
<div class="ion-padding" *ngIf="canMarkAllNotificationsAsRead">
<ion-button [disabled]="loadingMarkAllNotificationsAsRead" expand="block" (click)="markAllNotificationsAsRead()" fill="outline">
<ion-icon slot="start" name="fas-check" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
<ion-spinner slot="start" [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
</ion-spinner>
{{ 'addon.notifications.markallread' | translate }}
</ion-button>
</div>
<ion-item *ngFor="let notification of notifications" class="ion-text-wrap" [attr.aria-label]="
notification.timeread
? notification.subject
: 'addon.notifications.unreadnotification' | translate: {$a: notification.subject}"
(click)="openNotification(notification)" button [detail]="true" lines="true">
(click)="openNotification(notification)" button [detail]="false" lines="full">
<core-user-avatar *ngIf="notification.useridfrom > 0" [user]="notification" slot="start"
[profileUrl]="notification.profileimageurlfrom" [fullname]="notification.userfromfullname"
[userId]="notification.useridfrom">
@ -56,13 +47,12 @@
<core-format-text [text]="notification.subject" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
</core-format-text>
</p>
<p *ngIf="notification.useridfrom > 0">{{ notification.userfromfullname }}</p>
<p>{{ notification.timecreated | coreTimeAgo }}<ng-container *ngIf="notification.useridfrom > 0"> · {{
notification.userfromfullname }}</ng-container>
</p>
</ion-label>
<ion-note slot="end">
{{ notification.timecreated | coreDateDayOrTime }}
<span *ngIf="!notification.timeread">
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
</span>
<ion-note slot="end" *ngIf="!notification.timeread">
<ion-icon name="fas-circle" color="primary" aria-hidden="true"></ion-icon>
</ion-note>
</ion-item>
@ -72,4 +62,15 @@
<core-infinite-loading [enabled]="canLoadMore" (action)="loadMoreNotifications($event)" [error]="loadMoreError">
</core-infinite-loading>
</core-loading>
<div class="mark-all-as-read" slot="fixed" collapsible-footer appearOnBottom>
<ion-chip *ngIf="notificationsLoaded && canMarkAllNotificationsAsRead" [disabled]="loadingMarkAllNotificationsAsRead"
color="primary" (click)="markAllNotificationsAsRead()">
<ion-icon name="fas-eye" aria-hidden="true" *ngIf="!loadingMarkAllNotificationsAsRead"></ion-icon>
<ion-spinner [attr.aria-label]="'core.loading' | translate" *ngIf="loadingMarkAllNotificationsAsRead">
</ion-spinner>
{{ 'addon.notifications.markallread' | translate }}
</ion-chip>
</div>
</ion-content>

View File

@ -0,0 +1,72 @@
@import "~theme/globals";
ion-item {
ion-label {
margin-top: 8px;
margin-bottom: 8px;
p.item-heading {
font-size: 14px;
-webkit-line-clamp: 3;
overflow: hidden;
text-overflow: ellipsis;
-webkit-box-orient: vertical;
display: -webkit-box;
}
p {
font-size: 12px;
}
}
ion-note {
margin: 0;
@include padding-horizontal(8px, 0);
padding-top: 12px;
ion-icon {
font-size: 6px;
vertical-align: middle;
}
}
[slot=start] {
align-self: start;
margin-top: 16px;
}
--icon-size: 16px;
--extra-icon-size: 12px;
--core-avatar-size: 32px;
div.core-notification-icon,
core-mod-icon.core-notification-icon {
padding: 8px;
}
}
.mark-all-as-read {
padding-bottom: 16px;
bottom: 0;
left: 0;
right: 0;
display: flex;
background: transparent;
box-shadow: none;
pointer-events: none;
ion-chip.ion-color {
pointer-events: all;
margin: 0 auto;
box-shadow: 0 2px 4px rgba(0, 0, 0, .4);
ion-spinner {
width: 16px;
height: 16px;
@include margin-horizontal(0, 8px);
}
}
}
ion-content::part(scroll) {
padding-bottom: 44px;
}

View File

@ -39,7 +39,7 @@ import { CoreTimeUtils } from '@services/utils/time';
@Component({
selector: 'page-addon-notifications-list',
templateUrl: 'list.html',
styleUrls: ['../../notifications.scss'],
styleUrls: ['list.scss', '../../notifications.scss'],
})
export class AddonNotificationsListPage implements OnInit, OnDestroy {
@ -157,22 +157,6 @@ export class AddonNotificationsListPage implements OnInit, OnDestroy {
await this.refreshNotifications();
}
/**
* Mark notifications as read.
*
* @param notification Array of notification objects.
* @return Promise resolved when done.
*/
protected async markNotificationAsRead(notification: AddonNotificationsNotificationToRender): Promise<void> {
const updated = await AddonNotificationsHelper.markNotificationAsRead(notification);
if (!updated) {
return;
}
await this.loadMarkAllAsReadButton();
}
/**
* Load mark all notifications as read button.
*

View File

@ -11,45 +11,42 @@
<ion-content>
<core-loading [hideUntil]="loaded">
<div class="list-item-limited-width">
<ion-card>
<ion-item class="ion-text-wrap">
<core-user-avatar *ngIf="userIdFrom > 0" slot="start" [userId]="userIdFrom" [profileUrl]="profileImageUrlFrom"
[fullname]="userFromFullName">
<div class="core-avatar-extra-img" *ngIf="iconUrl && !modname">
<img [src]="iconUrl" alt="" role="presentation">
</div>
<core-mod-icon *ngIf="modname" [modicon]="iconUrl" [modname]="modname" [showAlt]="false">
</core-mod-icon>
</core-user-avatar>
<ion-item class="ion-text-wrap core-notification-title" lines="full">
<core-user-avatar *ngIf="userIdFrom > 0" slot="start" [userId]="userIdFrom" [profileUrl]="profileImageUrlFrom"
[fullname]="userFromFullName">
<div class="core-avatar-extra-img" *ngIf="iconUrl && !modname">
<img [src]="iconUrl" alt="" role="presentation">
</div>
<core-mod-icon *ngIf="modname" [modicon]="iconUrl" [modname]="modname" [showAlt]="false">
</core-mod-icon>
</core-user-avatar>
<ng-container *ngIf="userIdFrom <= 0 && iconUrl">
<div class="core-notification-icon" *ngIf="!modname" slot="start">
<img [src]="iconUrl" alt="" role="presentation">
</div>
<core-mod-icon *ngIf="modname" [modicon]="iconUrl" [modname]="modname" [showAlt]="false"
class="core-notification-icon" slot="start">
</core-mod-icon>
</ng-container>
<ng-container *ngIf="userIdFrom <= 0 && iconUrl">
<div class="core-notification-icon" *ngIf="!modname" slot="start">
<img [src]="iconUrl" alt="" role="presentation">
</div>
<core-mod-icon *ngIf="modname" [modicon]="iconUrl" [modname]="modname" [showAlt]="false" class="core-notification-icon"
slot="start">
</core-mod-icon>
</ng-container>
<ion-label>
<ion-card-subtitle *ngIf="userIdFrom > 0">{{ userFromFullName }}</ion-card-subtitle>
<ion-card-title>
<core-format-text [text]="subject" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
</core-format-text>
</ion-card-title>
</ion-label>
<ion-note slot="end" *ngIf="timecreated">
{{ timecreated | coreDateDayOrTime }}
</ion-note>
</ion-item>
<ion-item class="ion-text-wrap">
<ion-label>
<core-format-text [text]="content | coreCreateLinks" contextLevel="system" [contextInstanceId]="0">
<ion-label>
<p class="item-heading">
<core-format-text [text]="subject" contextLevel="system" [contextInstanceId]="0" [wsNotFiltered]="true">
</core-format-text>
</ion-label>
</ion-item>
</ion-card>
</p>
<p>{{ timecreated | coreTimeAgo }}<ng-container *ngIf="userIdFrom > 0"> · {{
userFromFullName }}</ng-container>
</p>
</ion-label>
</ion-item>
<ion-item class="ion-text-wrap core-notification-body">
<ion-label>
<core-format-text [text]="content | coreCreateLinks" contextLevel="system" [contextInstanceId]="0">
</core-format-text>
</ion-label>
</ion-item>
</div>
<div collapsible-footer appearOnBottom *ngIf="loaded && actions && actions.length > 0" slot="fixed">

View File

@ -2,67 +2,86 @@
:host {
h2 {
font-weight: bold;
.core-notification-title {
[slot=start] {
align-self: start;
margin-top: 16px;
}
p.item-heading {
font-size: 16px;
}
p {
font-size: 12px;
}
}
core-format-text ::ng-deep {
.forumpost {
border: 1px solid var(--gray-200);
width: 100%;
margin: 0 0 1em 0;
.core-notification-body {
core-format-text {
font-size: 14px;
}
td {
padding: 10px;
}
h2 {
font-weight: bold;
}
.header {
background-color: var(--light);
core-format-text ::ng-deep {
.forumpost {
border: 1px solid var(--gray-200);
width: 100%;
margin: 0 0 1em 0;
.picture {
width: 48px;
text-align: center;
@include padding-horizontal(4px, 0px);
padding-top: 8px;
td {
padding: 10px;
}
img {
width: 44px !important;
.header {
background-color: var(--light);
.picture {
width: 48px;
text-align: center;
@include padding-horizontal(4px, 0px);
padding-top: 8px;
img {
width: 44px !important;
}
}
}
.subject {
font-weight: 700;
margin-bottom: 1rem;
}
}
.subject {
font-weight: 700;
margin-bottom: 1rem;
}
}
a {
text-decoration: none;
}
.userpicture {
border-radius: 50%;
}
.mdl-right {
text-align: end;
a {
text-decoration: none;
}
.userpicture {
border-radius: 50%;
}
.mdl-right {
text-align: end;
a {
display: none;
}
font {
font-size: 0.9em;
}
}
.commands {
display: none;
}
font {
font-size: 0.9em;
hr {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
background-color: var(--gray-200);
}
}
.commands {
display: none;
}
hr {
margin-top: 1.5rem;
margin-bottom: 1.5rem;
background-color: var(--gray-200);
}
}
}