diff --git a/src/addons/messages/pages/discussion/discussion.html b/src/addons/messages/pages/discussion/discussion.html index bb9cc05ff..f5c3e8dba 100644 --- a/src/addons/messages/pages/discussion/discussion.html +++ b/src/addons/messages/pages/discussion/discussion.html @@ -81,47 +81,16 @@ - - - -
- -
{{ members[message.useridfrom].fullname }}
-
-
- {{ message.useridfrom == currentUserId - ? ('addon.messages.you' | translate) - : members[message.useridfrom].fullname }} -
- - -
- -
-
- {{ message.timecreated | coreFormatDate: "strftimetime" }} - - - - - - - -
-
+ + + [message]="'addon.messages.nomessagesfound' | translate"> + diff --git a/src/addons/messages/pages/discussion/discussion.page.ts b/src/addons/messages/pages/discussion/discussion.page.ts index 4f009de55..17cca33e9 100644 --- a/src/addons/messages/pages/discussion/discussion.page.ts +++ b/src/addons/messages/pages/discussion/discussion.page.ts @@ -37,7 +37,6 @@ import { CoreApp } from '@services/app'; import { CoreInfiniteLoadingComponent } from '@components/infinite-loading/infinite-loading'; import { Md5 } from 'ts-md5/dist/md5'; import moment from 'moment'; -import { CoreAnimations } from '@components/animations'; import { CoreError } from '@classes/errors/error'; import { Translate } from '@singletons'; import { CoreNavigator } from '@services/navigator'; @@ -53,7 +52,6 @@ import { CoreDom } from '@singletons/dom'; @Component({ selector: 'page-addon-messages-discussion', templateUrl: 'discussion.html', - animations: [CoreAnimations.SLIDE_IN_OUT], styleUrls: ['discussion.scss'], }) export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterViewInit { @@ -305,7 +303,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView } else { if (this.userId) { // Fake the user member info. - promises.push(CoreUser.getProfile(this.userId!).then(async (user) => { + promises.push(CoreUser.getProfile(this.userId).then(async (user) => { this.otherMember = { id: user.id, fullname: user.fullname, @@ -524,7 +522,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView return; } - const messages = Array.from(this.hostElement.querySelectorAll('.addon-message-not-mine')) + const messages = Array.from(this.hostElement.querySelectorAll('core-message:not(.is-mine)')) .slice(-this.newMessages) .reverse(); @@ -555,7 +553,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView // Try to get the conversationId if we don't have it. if (!conversationId && userId) { try { - if (userId == this.currentUserId && AddonMessages.isSelfConversationEnabled()) { + if (userId === this.currentUserId && AddonMessages.isSelfConversationEnabled()) { fallbackConversation = await AddonMessages.getSelfConversation(); } else { fallbackConversation = await AddonMessages.getConversationBetweenUsers(userId, undefined, true); @@ -563,7 +561,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView conversationId = fallbackConversation.id; } catch (error) { // Probably conversation does not exist or user is offline. Try to load offline messages. - this.isSelf = userId == this.currentUserId; + this.isSelf = userId === this.currentUserId; const messages = await AddonMessagesOffline.getMessages(userId); @@ -584,11 +582,15 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView } } + if (!conversationId) { + return false; + } + // Retrieve the conversation. Invalidate data first to get the right unreadcount. - await AddonMessages.invalidateConversation(conversationId!); + await AddonMessages.invalidateConversation(conversationId); try { - this.conversation = await AddonMessages.getConversation(conversationId!, undefined, true); + this.conversation = await AddonMessages.getConversation(conversationId, undefined, true); } catch (error) { // Get conversation failed, use the fallback one if we have it. if (fallbackConversation) { @@ -947,7 +949,6 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView message: AddonMessagesConversationMessageFormatted, index: number, ): Promise { - const canDeleteAll = this.conversation && this.conversation.candeletemessagesforallusers; const langKey = message.pending || canDeleteAll || this.isSelf ? 'core.areyousure' : 'addon.messages.deletemessageconfirmation'; @@ -1099,7 +1100,7 @@ export class AddonMessagesDiscussionPage implements OnInit, OnDestroy, AfterView */ scrollToFirstUnreadMessage(): void { if (this.newMessages > 0) { - const messages = Array.from(this.hostElement.querySelectorAll('.addon-message-not-mine')); + const messages = Array.from(this.hostElement.querySelectorAll('core-message:not(.is-mine)')); CoreDom.scrollToElement(messages[messages.length - this.newMessages]); } diff --git a/src/addons/messages/tests/behat/basic_usage.feature b/src/addons/messages/tests/behat/basic_usage.feature index c84ed18fd..0fcc067db 100755 --- a/src/addons/messages/tests/behat/basic_usage.feature +++ b/src/addons/messages/tests/behat/basic_usage.feature @@ -106,7 +106,6 @@ Feature: Test basic usage of messages in app And I should find "hi" in the app And I should find "byee" in the app - # TODO Fix this test in all Moodle versions Scenario: User profile: send message, add/remove contact Given I entered the app as "teacher1" When I press "Messages" in the app diff --git a/src/addons/mod/chat/pages/chat/chat.html b/src/addons/mod/chat/pages/chat/chat.html index cc3112b5b..dafc0260e 100644 --- a/src/addons/mod/chat/pages/chat/chat.html +++ b/src/addons/mod/chat/pages/chat/chat.html @@ -81,27 +81,10 @@ - - - -

- - -
{{ message.userfullname }}
-

- -
- - -
-
- {{ message.timestamp * 1000 | coreFormatDate: "strftimetime" }} -
-
+ + diff --git a/src/addons/mod/chat/pages/chat/chat.ts b/src/addons/mod/chat/pages/chat/chat.ts index 01cfcdb99..0fce55789 100644 --- a/src/addons/mod/chat/pages/chat/chat.ts +++ b/src/addons/mod/chat/pages/chat/chat.ts @@ -13,7 +13,6 @@ // limitations under the License. import { Component, ViewChild, OnInit, OnDestroy } from '@angular/core'; -import { CoreAnimations } from '@components/animations'; import { CoreSendMessageFormComponent } from '@components/send-message-form/send-message-form'; import { CanLeave } from '@guards/can-leave'; import { IonContent } from '@ionic/angular'; @@ -36,7 +35,6 @@ import { AddonModChatFormattedMessage, AddonModChatHelper } from '../../services @Component({ selector: 'page-addon-mod-chat-chat', templateUrl: 'chat.html', - animations: [CoreAnimations.SLIDE_IN_OUT], styleUrls: ['chat.scss'], }) export class AddonModChatChatPage implements OnInit, OnDestroy, CanLeave { diff --git a/src/addons/mod/chat/pages/session-messages/session-messages.html b/src/addons/mod/chat/pages/session-messages/session-messages.html index 9e18962a8..fd9f65e02 100644 --- a/src/addons/mod/chat/pages/session-messages/session-messages.html +++ b/src/addons/mod/chat/pages/session-messages/session-messages.html @@ -75,26 +75,9 @@ - - - -

- - -
{{ message.userfullname }}
-

- -
- - -
-
- {{ message.timestamp * 1000 | coreFormatDate: "strftimetime" }} -
-
+ + diff --git a/src/core/components/animations.ts b/src/core/components/animations.ts index 0f5d36215..d149fe5e2 100644 --- a/src/core/components/animations.ts +++ b/src/core/components/animations.ts @@ -36,7 +36,7 @@ export class CoreAnimations { animate(300, keyframes([ style({ opacity: 0, transform: 'translateX(-100%)', offset: 0 }), style({ opacity: 1, transform: 'translateX(5%)', offset: 0.7 }), - style({ opacity: 1, transform: 'translateX(0)', offset: 1.0 }), + style({ opacity: 1, transform: 'translateX(0)', offset: 1 }), ])), ]), // Leave animation. @@ -44,7 +44,7 @@ export class CoreAnimations { animate(300, keyframes([ style({ opacity: 1, transform: 'translateX(0)', offset: 0 }), style({ opacity: 1, transform: 'translateX(5%)', offset: 0.3 }), - style({ opacity: 0, transform: 'translateX(-100%)', offset: 1.0 }), + style({ opacity: 0, transform: 'translateX(-100%)', offset: 1 }), ])), ]), // Enter animation. @@ -52,7 +52,7 @@ export class CoreAnimations { animate(300, keyframes([ style({ opacity: 0, transform: 'translateX(100%)', offset: 0 }), style({ opacity: 1, transform: 'translateX(-5%)', offset: 0.7 }), - style({ opacity: 1, transform: 'translateX(0)', offset: 1.0 }), + style({ opacity: 1, transform: 'translateX(0)', offset: 1 }), ])), ]), // Leave animation. @@ -60,7 +60,7 @@ export class CoreAnimations { animate(300, keyframes([ style({ opacity: 1, transform: 'translateX(0)', offset: 0 }), style({ opacity: 1, transform: 'translateX(-5%)', offset: 0.3 }), - style({ opacity: 0, transform: 'translateX(100%)', offset: 1.0 }), + style({ opacity: 0, transform: 'translateX(100%)', offset: 1 }), ])), ]), ]); diff --git a/src/core/components/components.module.ts b/src/core/components/components.module.ts index 2ab8a0a30..7ad2d0279 100644 --- a/src/core/components/components.module.ts +++ b/src/core/components/components.module.ts @@ -61,6 +61,7 @@ import { CoreHorizontalScrollControlsComponent } from './horizontal-scroll-contr import { CoreButtonWithSpinnerComponent } from './button-with-spinner/button-with-spinner'; import { CoreSwipeSlidesComponent } from './swipe-slides/swipe-slides'; import { CoreSwipeNavigationTourComponent } from './swipe-navigation-tour/swipe-navigation-tour'; +import { CoreMessageComponent } from './message/message'; @NgModule({ declarations: [ @@ -84,6 +85,7 @@ import { CoreSwipeNavigationTourComponent } from './swipe-navigation-tour/swipe- CoreLoadingComponent, CoreLocalFileComponent, CoreMarkRequiredComponent, + CoreMessageComponent, CoreModIconComponent, CoreNavBarButtonsComponent, CoreNavigationBarComponent, @@ -134,6 +136,7 @@ import { CoreSwipeNavigationTourComponent } from './swipe-navigation-tour/swipe- CoreLoadingComponent, CoreLocalFileComponent, CoreMarkRequiredComponent, + CoreMessageComponent, CoreModIconComponent, CoreNavBarButtonsComponent, CoreNavigationBarComponent, diff --git a/src/core/components/message/message.html b/src/core/components/message/message.html new file mode 100644 index 000000000..80ee993ad --- /dev/null +++ b/src/core/components/message/message.html @@ -0,0 +1,45 @@ +
+
+ +
+ +
{{ userFullname }}
+
+
+ {{ isMine + ? ('addon.messages.you' | translate) + : userFullname }} +
+ + + +
+ +
+
+ + {{ time | coreFormatDate: 'strftimetime' }} + + + + + {{ 'core.deletedoffline' | translate }} + + + +
+ + + + + + + +
+ +
+
diff --git a/src/core/components/message/message.scss b/src/core/components/message/message.scss new file mode 100644 index 000000000..64b90e61c --- /dev/null +++ b/src/core/components/message/message.scss @@ -0,0 +1,138 @@ +@import "~theme/globals"; + +:host { + --message-background: var(--core-messages-message-bg); + --message-activated-background: var(--core-messages-message-activated-bg); + --message-alignment: flex-start; + + display: flex; + justify-content: var(--message-alignment); + + + .message-box { + --background: var(--message-background); + --min-height: var(--a11y-min-target-size); + + display: flex; + flex-direction: row; + position: relative; + + border: 0; + border-radius: var(--medium-radius); + margin: 8px; + width: 90%; + max-width: var(--list-item-max-width); + min-height: 36px; + + font-size: var(--text-size); + color: var(--ion-text-color); + + background: var(--message-background); + @include core-transition(width); + + // This is needed to display bubble tails. + overflow: visible; + + &:hover { + -webkit-filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3)); + filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3)); + } + + &[tappable]:active { + --message-background: var(--message-activated-background); + } + + .main { + padding: 8px; + flex-grow: 1; + + .message-user { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + margin-bottom: .5rem; + margin-top: 0; + color: var(--ion-text-color); + + core-user-avatar { + display: block; + --core-avatar-size: var(--core-messages-avatar-size); + margin: 0; + } + + div { + font-weight: 500; + flex-grow: 1; + padding-left: .5rem; + padding-right: .5rem; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; + font-size: 16px; + } + } + + .message-text { + ::ng-deep > p:only-child { + display: inline; + margin: 0; + } + } + } + + .extra { + flex-shrink: 1; + display: flex; + flex-direction: row; + padding-left: 8px; + padding-right: 8px; + + .message-time { + padding-top: 8px; + color: var(--core-messages-message-note-text); + font-size: var(--core-messages-message-note-font-size); + } + + .delete-button { + min-height: initial; + line-height: initial; + margin: 0px; + align-self: flex-end; + + ::ng-deep ion-icon { + font-size: 1.2em; + } + } + } + + .tail { + content: ''; + width: 0; + height: 0; + border: 0.5rem solid transparent; + position: absolute; + touch-action: none; + bottom: 0; + border-bottom-color: var(--message-background); + @include position(null, null, null, -8px); + } + } + + &.no-user .message-box { + margin-top: 0px; + } + + &.is-mine { + // Defined when a message is the user's. + --message-background: var(--core-messages-message-mine-bg); + --message-activated-background: var(--core-messages-message-mine-activated-bg); + --message-alignment: flex-end; + + .message-box { + .tail { + @include position(null, -8px, null, unset); + } + } + } +} diff --git a/src/core/components/message/message.ts b/src/core/components/message/message.ts new file mode 100644 index 000000000..818638aef --- /dev/null +++ b/src/core/components/message/message.ts @@ -0,0 +1,121 @@ +// (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 { ContextLevel } from '@/core/constants'; +import { Component, EventEmitter, HostBinding, Input, OnInit, Output } from '@angular/core'; +import { CoreAnimations } from '@components/animations'; +import { CoreSites } from '@services/sites'; +import { CoreUtils } from '@services/utils/utils'; +import { CoreTextUtils } from '@services/utils/text'; +import { CoreUserWithAvatar } from '@components/user-avatar/user-avatar'; + +/** + * Component to handle a message in a conversation. + */ +@Component({ + selector: 'core-message', + templateUrl: 'message.html', + styleUrls: ['message.scss'], + animations: [CoreAnimations.SLIDE_IN_OUT], +}) +export class CoreMessageComponent implements OnInit { + + @Input() message?: CoreMessageData; // The message object. + @Input() user?: CoreUserWithAvatar; // The user object. + + @Input() text = ''; // Message text. + @Input() time = 0; // Message time. + @Input() instanceId = 0; + @Input() courseId?: number; + @Input() contextLevel: ContextLevel = ContextLevel.SYSTEM; + @Input() showDelete = false; + @Output() onDeleteMessage = new EventEmitter(); + @Output() onUndoDeleteMessage = new EventEmitter(); + @Output() afterRender = new EventEmitter(); + + protected deleted = false; // Needed to fix animation to void in Behat tests. + + // @TODO Recover the animation using native css or wait for Angular 13.1 + // where the bug https://github.com/angular/angular/issues/30693 is solved. + // @HostBinding('@coreSlideInOut') get animation(): string { + // return this.isMine ? '' : 'fromLeft'; + // } + + @HostBinding('class.is-mine') isMine = false; + + @HostBinding('class.no-user') get showUser(): boolean { + return !this.message?.showUserData; + }; + + get userId(): number | undefined { + return this.user && (this.user.userid || this.user.id); + } + + get userFullname(): string | undefined { + return this.user && (this.user.fullname || this.user.userfullname); + } + + /** + * @inheritdoc + */ + async ngOnInit(): Promise { + const currentUserId = CoreSites.getCurrentSiteUserId(); + + this.isMine = this.userId === currentUserId; + } + + /** + * Emits the delete action. + * + * @param event Event. + */ + delete(event: Event): void { + event.preventDefault(); + event.stopPropagation(); + this.onDeleteMessage.emit(); + } + + /** + * Emits the undo delete action. + * + * @param event Event. + */ + undoDelete(event: Event): void { + event.preventDefault(); + event.stopPropagation(); + this.onUndoDeleteMessage.emit(); + + } + + /** + * Copy message to clipboard. + */ + copyMessage(): void { + CoreUtils.copyToClipboard(CoreTextUtils.decodeHTMLEntities(this.text)); + } + +} + +/** + * Conversation message with some calculated data. + */ +type CoreMessageData = { + pending?: boolean; // Whether the message is pending to be sent. + sending?: boolean; // Whether the message is being sent right now. + showDate?: boolean; // Whether to show the date before the message. + deleted?: boolean; // Whether the message has been deleted. + showUserData?: boolean; // Whether to show the user data in the message. + showTail?: boolean; // Whether to show a "tail" in the message. + delete?: boolean; // Permission to delete=true/false. +}; diff --git a/src/core/components/user-avatar/user-avatar.ts b/src/core/components/user-avatar/user-avatar.ts index 96f7afd80..85a087c19 100644 --- a/src/core/components/user-avatar/user-avatar.ts +++ b/src/core/components/user-avatar/user-avatar.ts @@ -156,7 +156,7 @@ export class CoreUserAvatarComponent implements OnInit, OnChanges, OnDestroy { /** * Type with all possible formats of user. */ -type CoreUserWithAvatar = CoreUserBasicData & { +export type CoreUserWithAvatar = CoreUserBasicData & { userpictureurl?: string; userprofileimageurl?: string; profileimageurlsmall?: string; diff --git a/src/core/features/comments/pages/viewer/viewer.html b/src/core/features/comments/pages/viewer/viewer.html index 94ed52d8d..0df89ba27 100644 --- a/src/core/features/comments/pages/viewer/viewer.html +++ b/src/core/features/comments/pages/viewer/viewer.html @@ -45,71 +45,20 @@ {{ comment.timecreated * 1000 | coreFormatDate: "strftimedayshort" }}

- - - -

- - -
{{ comment.fullname }}
-

- -
- - -
-
- - - {{ comment.timecreated * 1000 | coreFormatDate: 'strftimetime' }} - - - - {{ 'core.deletedoffline' | translate }} - - - -
- - - - - - -
+ + - - - -

- - {{ 'core.thereisdatatosync' | translate:{$a: 'core.comments.comments' | translate | lowercase } }} -

- -
- - -
-
- - {{ 'core.notsent' | translate }} - -
- - - -
+ + + {{ 'core.thereisdatatosync' | translate:{$a: 'core.comments.comments' | translate | lowercase } }} + + + diff --git a/src/core/features/comments/pages/viewer/viewer.page.ts b/src/core/features/comments/pages/viewer/viewer.page.ts index 6e46394cf..4b79eedfe 100644 --- a/src/core/features/comments/pages/viewer/viewer.page.ts +++ b/src/core/features/comments/pages/viewer/viewer.page.ts @@ -14,7 +14,6 @@ import { Component, OnDestroy, OnInit, ViewChild } from '@angular/core'; import { CoreEventObserver, CoreEvents } from '@singletons/events'; -import { CoreAnimations } from '@components/animations'; import { ActivatedRoute } from '@angular/router'; import { CoreSites } from '@services/sites'; import { @@ -43,6 +42,7 @@ import { CoreApp } from '@services/app'; import { CoreNetwork } from '@services/network'; import moment from 'moment'; import { Subscription } from 'rxjs'; +import { CoreAnimations } from '@components/animations'; /** * Page that displays comments. @@ -75,7 +75,7 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { hasOffline = false; refreshIcon = CoreConstants.ICON_LOADING; syncIcon = CoreConstants.ICON_LOADING; - offlineComment?: CoreCommentsOfflineWithUser; + offlineComment?: CoreCommentsOfflineWithUser & { pending?: boolean }; currentUserId: number; sending = false; newComment = ''; @@ -361,13 +361,9 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { /** * Delete a comment. * - * @param e Click event. * @param comment Comment to delete. */ - async deleteComment(e: Event, comment: CoreCommentsDataToDisplay | CoreCommentsOfflineWithUser): Promise { - e.preventDefault(); - e.stopPropagation(); - + async deleteComment(comment: CoreCommentsDataToDisplay | CoreCommentsOfflineWithUser): Promise { const modified = 'lastmodified' in comment ? comment.lastmodified : comment.timecreated; @@ -529,15 +525,16 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { ).then(async (offlineComment) => { this.offlineComment = offlineComment; - if (!offlineComment) { + if (!this.offlineComment) { return; } if (this.newComment == '') { - this.newComment = this.offlineComment!.content; + this.newComment = this.offlineComment.content; } - this.offlineComment!.userid = this.currentUserId; + this.offlineComment.userid = this.currentUserId; + this.offlineComment.pending = true; return; })); @@ -573,13 +570,9 @@ export class CoreCommentsViewerPage implements OnInit, OnDestroy { /** * Restore a comment. * - * @param e Click event. * @param comment Comment to delete. */ - async undoDeleteComment(e: Event, comment: CoreCommentsDataToDisplay): Promise { - e.preventDefault(); - e.stopPropagation(); - + async undoDeleteComment(comment: CoreCommentsDataToDisplay): Promise { await CoreCommentsOffline.undoDeleteComment(comment.id); comment.deleted = false; diff --git a/src/core/features/comments/pages/viewer/viewer.scss b/src/core/features/comments/pages/viewer/viewer.scss index 7fb2d0cc4..cf231da48 100644 --- a/src/core/features/comments/pages/viewer/viewer.scss +++ b/src/core/features/comments/pages/viewer/viewer.scss @@ -1 +1,5 @@ @import "~theme/components/discussion.scss"; + +ion-badge { + margin: 8px auto; +} diff --git a/src/theme/components/discussion.scss b/src/theme/components/discussion.scss index 540188a0e..fcb653a9d 100644 --- a/src/theme/components/discussion.scss +++ b/src/theme/components/discussion.scss @@ -27,148 +27,3 @@ ion-content { font-weight: normal; font-size: 0.9rem; } - -// Message item. -ion-item.addon-message { - --message-background: var(--addon-messages-message-bg); - --message-activated-background: var(--addon-messages-message-activated-bg); - --message-alignment: flex-start; - - border: 0; - border-radius: var(--medium-radius); - padding: 0 8px 0 8px; - margin: 8px; - --background: var(--message-background); - background: var(--message-background); - align-self: var(--message-alignment); - width: 90%; - max-width: var(--list-item-max-width); - --min-height: var(--a11y-min-target-size); - position: relative; - @include core-transition(width); - // This is needed to display bubble tails. - overflow: visible; - - &::part(native) { - --inner-border-width: 0px; - --inner-padding-end: 0px; - padding: 0; - margin: 0; - } - - &:hover { - -webkit-filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3)); - filter: drop-shadow(2px 2px 2px rgba(0,0,0,.3)); - } - - core-format-text > p:only-child { - display: inline; - } - - .addon-message-user { - display: flex; - flex-direction: row; - justify-content: space-between; - align-items: center; - margin-bottom: .5rem; - margin-top: 0; - color: var(--ion-text-color); - - core-user-avatar { - display: block; - --core-avatar-size: var(--addon-messages-avatar-size); - margin: 0; - } - - div { - font-weight: 500; - flex-grow: 1; - padding-left: .5rem; - padding-right: .5rem; - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; - } - } - - ion-note { - color: var(--addon-messages-message-note-text); - font-size: var(--addon-messages-message-note-font-size); - margin: 0; - padding: 8px 0; - align-self: flex-start; - } - - &[tappable]:active { - --message-background: var(--message-activated-background); - } - - ion-label { - margin: 0; - padding: 8px 0; - } - - .addon-message-text { - display: inline-flex; - * { - color: var(--ion-text-color); - } - } - - .tail { - content: ''; - width: 0; - height: 0; - border: 0.5rem solid transparent; - position: absolute; - touch-action: none; - bottom: 0; - border-bottom-color: var(--message-background); - } - - // Defines when an item-message is the user's. - &.addon-message-mine { - --message-background: var(--addon-messages-message-mine-bg); - --message-activated-background: var(--addon-messages-message-mine-activated-bg); - --message-alignment: flex-end; - - .spinner { - @include float(end); - @include margin(2px, -3px, -2px, 5px); - - svg { - width: 16px; - height: 16px; - } - } - - .tail { - @include position(null, -8px, null, null); - @include margin-horizontal(null, -0.5rem); - } - } - - &.addon-message-not-mine .tail { - @include position(null, null, null, -8px); - @include margin-horizontal(-0.5rem, null); - } - - .addon-messages-delete-button { - min-height: initial; - line-height: initial; - margin-top: 0px; - margin-bottom: 0px; - height: var(--a11y-min-target-size) !important; - align-self: flex-end; - - ion-icon { - font-size: 1.4em; - line-height: initial; - color: var(--danger); - } - } - - &.addon-message-no-user { - margin-top: 0px; - } -} diff --git a/src/theme/theme.dark.scss b/src/theme/theme.dark.scss index ecd188b0c..a526f82ea 100644 --- a/src/theme/theme.dark.scss +++ b/src/theme/theme.dark.scss @@ -146,13 +146,13 @@ --core-collapsible-footer-background: var(--contrast-background); - --addon-messages-message-bg: var(--gray-800); - --addon-messages-message-activated-bg: var(--gray-700); - --addon-messages-message-note-text: var(--subdued-text-color); - --addon-messages-message-mine-bg: var(--gray-700); - --addon-messages-message-mine-activated-bg: var(--gray-600); - --addon-messages-discussion-badge: var(--primary); - --addon-messages-discussion-badge-text: var(--gray-100); + --core-messages-message-bg: var(--gray-800); + --core-messages-message-activated-bg: var(--gray-700); + --core-messages-message-note-text: var(--subdued-text-color); + --core-messages-message-mine-bg: var(--gray-700); + --core-messages-message-mine-activated-bg: var(--gray-600); + --core-messages-discussion-badge: var(--primary); + --core-messages-discussion-badge-text: var(--gray-100); --addon-forum-border-color: var(--gray-500); --addon-forum-highlight-color: var(--gray-200); diff --git a/src/theme/theme.light.scss b/src/theme/theme.light.scss index f13f3aee1..780297398 100644 --- a/src/theme/theme.light.scss +++ b/src/theme/theme.light.scss @@ -344,15 +344,15 @@ --addon-calendar-today-border-color: var(--primary); --addon-calendar-border-color: var(--stroke); - --addon-messages-message-bg: var(--white); - --addon-messages-message-activated-bg: var(--gray-200); - --addon-messages-message-note-text: var(--gray-500); - --addon-messages-message-note-font-size: 75%; - --addon-messages-message-mine-bg: var(--gray-300); - --addon-messages-message-mine-activated-bg: var(--gray-400); - --addon-messages-avatar-size: 30px; - --addon-messages-discussion-badge: var(--primary); - --addon-messages-discussion-badge-text: var(--white); + --core-messages-message-bg: var(--white); + --core-messages-message-activated-bg: var(--gray-200); + --core-messages-message-note-text: var(--gray-500); + --core-messages-message-note-font-size: 75%; + --core-messages-message-mine-bg: var(--gray-300); + --core-messages-message-mine-activated-bg: var(--gray-400); + --core-messages-avatar-size: 30px; + --core-messages-discussion-badge: var(--primary); + --core-messages-discussion-badge-text: var(--white); --addon-forum-avatar-size: var(--core-avatar-size); --addon-forum-border-color: var(--stroke); diff --git a/upgrade.txt b/upgrade.txt index ead37e419..7576f9804 100644 --- a/upgrade.txt +++ b/upgrade.txt @@ -1,9 +1,10 @@ This files describes API changes in the Moodle Mobile app, information provided here is intended especially for developers. -=== 4.0.1 === +=== 4.1.0 === - Zoom levels changed from "normal / low / high" to " none / medium / high". +- --addon-messages-* CSS3 variables have been renamed to --core-messages-* === 4.0.0 ===