diff --git a/cypress/e2e/regression-tests/pills-click-in-app.spec.ts b/cypress/e2e/regression-tests/pills-click-in-app.spec.ts index 301da254da..8540736f3e 100644 --- a/cypress/e2e/regression-tests/pills-click-in-app.spec.ts +++ b/cypress/e2e/regression-tests/pills-click-in-app.spec.ts @@ -67,7 +67,7 @@ describe("Pills", () => { // go back to the message room and try to click on the pill text, as a user would cy.viewRoomByName(messageRoom); - cy.get(".mx_EventTile_body .mx_Pill .mx_Pill_linkText") + cy.get(".mx_EventTile_body .mx_Pill .mx_Pill_text") .should("have.css", "pointer-events", "none") .click({ force: true }); // force is to ensure we bypass pointer-events cy.url().should("contain", localUrl); diff --git a/res/css/views/elements/_Pill.pcss b/res/css/views/elements/_Pill.pcss index f3b44898a9..6cced8b8b5 100644 --- a/res/css/views/elements/_Pill.pcss +++ b/res/css/views/elements/_Pill.pcss @@ -29,6 +29,10 @@ limitations under the License. color: $accent-fg-color !important; /* To override .markdown-body */ background-color: $pill-bg-color !important; /* To override .markdown-body */ + > * { + pointer-events: none; + } + &.mx_UserPill_me, &.mx_AtRoomPill { background-color: $alert !important; /* To override .markdown-body */ @@ -55,12 +59,17 @@ limitations under the License. min-width: $font-16px; /* ensure the avatar is not compressed */ } - .mx_Pill_linkText { - white-space: nowrap; /* enforce the pill text to be a single line */ + &.mx_EventPill .mx_BaseAvatar { + /* Event pill avatars are inside the text. */ + margin-inline-start: 0.2em; + margin-inline-end: 0.2em; + } + + .mx_Pill_text { + min-width: 0; overflow: hidden; text-overflow: ellipsis; - - pointer-events: none; /* ensure clicks on the pills go through the anchor */ + white-space: nowrap; } a& { @@ -69,4 +78,20 @@ limitations under the License. overflow: hidden; text-decoration: none !important; /* To override .markdown-body */ } + + .mx_Pill_LinkIcon { + background-color: $link-external; + box-sizing: border-box; + color: $background; + height: 16px; + padding: 1px; + width: 16px; + } + + .mx_Pill_UserIcon { + box-sizing: border-box; + color: $secondary-content; + height: 16px; + width: 16px; + } } diff --git a/res/img/compound/user.svg b/res/img/compound/user.svg new file mode 100644 index 0000000000..fa8bb87cd1 --- /dev/null +++ b/res/img/compound/user.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/res/themes/legacy-dark/css/_legacy-dark.pcss b/res/themes/legacy-dark/css/_legacy-dark.pcss index 03088f216b..d26d3e20d3 100644 --- a/res/themes/legacy-dark/css/_legacy-dark.pcss +++ b/res/themes/legacy-dark/css/_legacy-dark.pcss @@ -90,6 +90,7 @@ $room-icon-unread-color: #fff; $accent: #0dbd8b; $alert: #ff5b55; $links: #0086e6; +$link-external: #0467dd; $primary-content: $primary-fg-color; $secondary-content: $secondary-fg-color; $tertiary-content: $tertiary-fg-color; diff --git a/res/themes/legacy-light/css/_legacy-light.pcss b/res/themes/legacy-light/css/_legacy-light.pcss index dd152f368e..26efa76517 100644 --- a/res/themes/legacy-light/css/_legacy-light.pcss +++ b/res/themes/legacy-light/css/_legacy-light.pcss @@ -149,6 +149,7 @@ $presence-busy: #ff5b55; $accent: #0dbd8b; $alert: #ff5b55; $links: #0086e6; +$link-external: #0467dd; $primary-content: $primary-fg-color; $secondary-content: $secondary-fg-color; $tertiary-content: $tertiary-fg-color; diff --git a/res/themes/light/css/_light.pcss b/res/themes/light/css/_light.pcss index 6d59801779..d7bfbcefab 100644 --- a/res/themes/light/css/_light.pcss +++ b/res/themes/light/css/_light.pcss @@ -41,6 +41,7 @@ $space-nav: rgba($tertiary-content, 0.15); $accent: #0dbd8b; $alert: #ff5b55; $links: #0086e6; +$link-external: #0467dd; $username-variant1-color: #368bd6; $username-variant2-color: #ac3ba8; diff --git a/src/components/views/elements/Pill.tsx b/src/components/views/elements/Pill.tsx index 1ccc3f36b5..ab0c2b7e2f 100644 --- a/src/components/views/elements/Pill.tsx +++ b/src/components/views/elements/Pill.tsx @@ -17,6 +17,7 @@ limitations under the License. import React, { ReactElement, useState } from "react"; import classNames from "classnames"; import { Room } from "matrix-js-sdk/src/models/room"; +import { RoomMember } from "matrix-js-sdk/src/matrix"; import { MatrixClientPeg } from "../../../MatrixClientPeg"; import MatrixClientContext from "../../../contexts/MatrixClientContext"; @@ -24,11 +25,16 @@ import Tooltip, { Alignment } from "../elements/Tooltip"; import { usePermalink } from "../../../hooks/usePermalink"; import RoomAvatar from "../avatars/RoomAvatar"; import MemberAvatar from "../avatars/MemberAvatar"; +import { _t } from "../../../languageHandler"; +import { Icon as LinkIcon } from "../../../../res/img/element-icons/room/composer/link.svg"; +import { Icon as UserIcon } from "../../../../res/img/compound/user.svg"; export enum PillType { UserMention = "TYPE_USER_MENTION", RoomMention = "TYPE_ROOM_MENTION", AtRoomMention = "TYPE_AT_ROOM_MENTION", // '@room' mention + EventInSameRoom = "TYPE_EVENT_IN_SAME_ROOM", + EventInOtherRoom = "TYPE_EVENT_IN_OTHER_ROOM", } export const pillRoomNotifPos = (text: string): number => { @@ -39,6 +45,34 @@ export const pillRoomNotifLen = (): number => { return "@room".length; }; +const PillRoomAvatar: React.FC<{ + shouldShowPillAvatar: boolean; + room: Room | null; +}> = ({ shouldShowPillAvatar, room }) => { + if (!shouldShowPillAvatar) { + return null; + } + + if (room) { + return