Skip to content
This repository has been archived by the owner on Sep 11, 2024. It is now read-only.

Commit

Permalink
Enlarge emoji in composer (#7602)
Browse files Browse the repository at this point in the history
  • Loading branch information
robintown authored Jan 24, 2022
1 parent b5d1133 commit 6806c2c
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 42 deletions.
5 changes: 5 additions & 0 deletions res/css/views/elements/_RichText.scss
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,11 @@ a.mx_Pill {
margin-right: 0.24rem;
}

.mx_Emoji {
font-size: 1.8rem;
vertical-align: bottom;
}

.mx_Markdown_BOLD {
font-weight: bold;
}
Expand Down
2 changes: 2 additions & 0 deletions res/css/views/rooms/_EventBubbleTile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,8 @@ limitations under the License.
.mx_EventTile_line {
width: fit-content;
max-width: 70%;
// fixed line height to prevent emoji from being taller than text
line-height: $font-18px;
}

> .mx_SenderProfile {
Expand Down
7 changes: 1 addition & 6 deletions res/css/views/rooms/_EventTile.scss
Original file line number Diff line number Diff line change
Expand Up @@ -233,11 +233,6 @@ $left-gutter: 64px;
overflow-y: hidden;
}

.mx_EventTile_Emoji {
font-size: 1.8rem;
vertical-align: bottom;
}

&.mx_EventTile_selected .mx_EventTile_line,
&:hover .mx_EventTile_line {
border-top-left-radius: 4px;
Expand Down Expand Up @@ -391,7 +386,7 @@ $left-gutter: 64px;
position: absolute;
}

.mx_EventTile_bigEmoji .mx_EventTile_Emoji {
.mx_EventTile_bigEmoji .mx_Emoji {
font-size: 48px !important;
line-height: 57px;
}
Expand Down
2 changes: 2 additions & 0 deletions res/css/views/rooms/_SendMessageComposer.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ limitations under the License.
display: flex;
flex-direction: column;
font-size: $font-14px;
// fixed line height to prevent emoji from being taller than text
line-height: calc(1.2 * $font-14px);
justify-content: center;
margin-right: 6px;
// don't grow wider than available space
Expand Down
7 changes: 3 additions & 4 deletions src/HtmlUtils.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,8 @@ const MEDIA_API_MXC_REGEX = /\/_matrix\/media\/r0\/(?:download|thumbnail)\/(.+?)
* Uses a much, much simpler regex than emojibase's so will give false
* positives, but useful for fast-path testing strings to see if they
* need emojification.
* unicodeToImage uses this function.
*/
function mightContainEmoji(str: string): boolean {
export function mightContainEmoji(str: string): boolean {
return SURROGATE_PAIR_PATTERN.test(str) || SYMBOL_PATTERN.test(str);
}

Expand Down Expand Up @@ -412,9 +411,9 @@ export interface IOptsReturnString extends IOpts {
}

const emojiToHtmlSpan = (emoji: string) =>
`<span class='mx_EventTile_Emoji' title='${unicodeToShortcode(emoji)}'>${emoji}</span>`;
`<span class='mx_Emoji' title='${unicodeToShortcode(emoji)}'>${emoji}</span>`;
const emojiToJsxSpan = (emoji: string, key: number) =>
<span key={key} className='mx_EventTile_Emoji' title={unicodeToShortcode(emoji)}>{ emoji }</span>;
<span key={key} className='mx_Emoji' title={unicodeToShortcode(emoji)}>{ emoji }</span>;

/**
* Wraps emojis in <span> to style them separately from the rest of message. Consecutive emojis (and modifiers) are wrapped
Expand Down
4 changes: 2 additions & 2 deletions src/components/views/rooms/BasicMessageComposer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>

// this returns the amount of added/removed characters during the replace
// so the caret position can be adjusted.
return range.replace([partCreator.plain(data.unicode)]);
return range.replace([partCreator.emoji(data.unicode)]);
}
}
}
Expand Down Expand Up @@ -831,7 +831,7 @@ export default class BasicMessageEditor extends React.Component<IProps, IState>
const caret = this.getCaret();
const position = model.positionForOffset(caret.offset, caret.atNodeEnd);
model.transform(() => {
const addedLen = model.insert([partCreator.plain(text)], position);
const addedLen = model.insert(partCreator.plainWithEmoji(text), position);
return model.positionForOffset(caret.offset + addedLen, true);
});
}
Expand Down
2 changes: 1 addition & 1 deletion src/editor/autocomplete.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ export default class AutocompleteWrapperModel {
return [(this.partCreator as CommandPartCreator).command(text)];
default:
// used for emoji and other plain text completion replacement
return [this.partCreator.plain(text)];
return this.partCreator.plainWithEmoji(text);
}
}
}
10 changes: 5 additions & 5 deletions src/editor/caret.ts
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ export function getLineAndNodePosition(model: EditorModel, caretPosition: IPosit
offset = 0;
} else {
// move caret out of uneditable part (into caret node, or empty line br) if needed
({ nodeIndex, offset } = moveOutOfUneditablePart(parts, partIndex, nodeIndex, offset));
({ nodeIndex, offset } = moveOutOfUnselectablePart(parts, partIndex, nodeIndex, offset));
}
return { lineIndex, nodeIndex, offset };
}
Expand All @@ -123,7 +123,7 @@ function findNodeInLineForPart(parts: Part[], partIndex: number) {
nodeIndex += 1;
}
// only jump over caret node if we're not at our destination node already,
// as we'll assume in moveOutOfUneditablePart that nodeIndex
// as we'll assume in moveOutOfUnselectablePart that nodeIndex
// refers to the node corresponding to the part,
// and not an adjacent caret node
if (i < partIndex) {
Expand All @@ -140,10 +140,10 @@ function findNodeInLineForPart(parts: Part[], partIndex: number) {
return { lineIndex, nodeIndex };
}

function moveOutOfUneditablePart(parts: Part[], partIndex: number, nodeIndex: number, offset: number) {
// move caret before or after uneditable part
function moveOutOfUnselectablePart(parts: Part[], partIndex: number, nodeIndex: number, offset: number) {
// move caret before or after unselectable part
const part = parts[partIndex];
if (part && !part.canEdit) {
if (part && !part.acceptsCaret) {
if (offset === 0) {
nodeIndex -= 1;
const prevPart = parts[partIndex - 1];
Expand Down
38 changes: 19 additions & 19 deletions src/editor/deserialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ function parseAtRoomMentions(text: string, partCreator: PartCreator): Part[] {
const parts: Part[] = [];
text.split(ATROOM).forEach((textPart, i, arr) => {
if (textPart.length) {
parts.push(partCreator.plain(textPart));
parts.push(...partCreator.plainWithEmoji(textPart));
}
// it's safe to never append @room after the last textPart
// as split will report an empty string at the end if
Expand All @@ -42,28 +42,28 @@ function parseAtRoomMentions(text: string, partCreator: PartCreator): Part[] {
return parts;
}

function parseLink(a: HTMLAnchorElement, partCreator: PartCreator): Part {
function parseLink(a: HTMLAnchorElement, partCreator: PartCreator): Part[] {
const { href } = a;
const resourceId = getPrimaryPermalinkEntity(href); // The room/user ID
const prefix = resourceId ? resourceId[0] : undefined; // First character of ID
switch (prefix) {
case "@":
return partCreator.userPill(a.textContent, resourceId);
return [partCreator.userPill(a.textContent, resourceId)];
case "#":
return partCreator.roomPill(resourceId);
return [partCreator.roomPill(resourceId)];
default: {
if (href === a.textContent) {
return partCreator.plain(a.textContent);
return partCreator.plainWithEmoji(a.textContent);
} else {
return partCreator.plain(`[${a.textContent.replace(/[[\\\]]/g, c => "\\" + c)}](${href})`);
return partCreator.plainWithEmoji(`[${a.textContent.replace(/[[\\\]]/g, c => "\\" + c)}](${href})`);
}
}
}
}

function parseImage(img: HTMLImageElement, partCreator: PartCreator): Part {
function parseImage(img: HTMLImageElement, partCreator: PartCreator): Part[] {
const { src } = img;
return partCreator.plain(`![${img.alt.replace(/[[\\\]]/g, c => "\\" + c)}](${src})`);
return partCreator.plainWithEmoji(`![${img.alt.replace(/[[\\\]]/g, c => "\\" + c)}](${src})`);
}

function parseCodeBlock(n: HTMLElement, partCreator: PartCreator): Part[] {
Expand All @@ -79,7 +79,7 @@ function parseCodeBlock(n: HTMLElement, partCreator: PartCreator): Part[] {
}
const preLines = ("```" + language + "\n" + n.textContent + "```").split("\n");
preLines.forEach((l, i) => {
parts.push(partCreator.plain(l));
parts.push(...partCreator.plainWithEmoji(l));
if (i < preLines.length - 1) {
parts.push(partCreator.newline());
}
Expand Down Expand Up @@ -126,21 +126,21 @@ function parseElement(
partCreator.newline(),
];
case "EM":
return partCreator.plain(`_${n.textContent}_`);
return partCreator.plainWithEmoji(`_${n.textContent}_`);
case "STRONG":
return partCreator.plain(`**${n.textContent}**`);
return partCreator.plainWithEmoji(`**${n.textContent}**`);
case "PRE":
return parseCodeBlock(n, partCreator);
case "CODE":
return partCreator.plain(`\`${n.textContent}\``);
return partCreator.plainWithEmoji(`\`${n.textContent}\``);
case "DEL":
return partCreator.plain(`<del>${n.textContent}</del>`);
return partCreator.plainWithEmoji(`<del>${n.textContent}</del>`);
case "SUB":
return partCreator.plain(`<sub>${n.textContent}</sub>`);
return partCreator.plainWithEmoji(`<sub>${n.textContent}</sub>`);
case "SUP":
return partCreator.plain(`<sup>${n.textContent}</sup>`);
return partCreator.plainWithEmoji(`<sup>${n.textContent}</sup>`);
case "U":
return partCreator.plain(`<u>${n.textContent}</u>`);
return partCreator.plainWithEmoji(`<u>${n.textContent}</u>`);
case "LI": {
const BASE_INDENT = 4;
const depth = state.listDepth - 1;
Expand Down Expand Up @@ -171,9 +171,9 @@ function parseElement(
((SdkConfig.get()['latex_maths_delims'] || {})['inline'] || {})['right'] || "\\)" :
((SdkConfig.get()['latex_maths_delims'] || {})['display'] || {})['right'] || "\\]";
const tex = n.getAttribute("data-mx-maths");
return partCreator.plain(delimLeft + tex + delimRight);
return partCreator.plainWithEmoji(delimLeft + tex + delimRight);
} else if (!checkDescendInto(n)) {
return partCreator.plain(n.textContent);
return partCreator.plainWithEmoji(n.textContent);
}
break;
}
Expand All @@ -186,7 +186,7 @@ function parseElement(
default:
// don't textify block nodes we'll descend into
if (!checkDescendInto(n)) {
return partCreator.plain(n.textContent);
return partCreator.plainWithEmoji(n.textContent);
}
}
}
Expand Down
Loading

0 comments on commit 6806c2c

Please sign in to comment.