Skip to content

Commit 88ba960

Browse files
authored
fix: cross-platform emoji compatibility (#1449)
1 parent 33a076c commit 88ba960

16 files changed

+300
-50
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
"afterSign": "scripts/notarize.js"
101101
},
102102
"dependencies": {
103+
"@discordapp/twemoji": "15.0.3",
103104
"@electron/remote": "2.1.2",
104105
"@primer/octicons-react": "19.11.0",
105106
"axios": "1.7.4",

pnpm-lock.yaml

Lines changed: 27 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/__mocks__/utils.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
export function setPlatform(platform: NodeJS.Platform) {
2-
Object.defineProperty(process, 'platform', {
3-
value: platform,
4-
});
1+
import * as helpers from '../utils/helpers';
2+
3+
export function mockDirectoryPath() {
4+
jest.spyOn(helpers, 'getDirectoryPath').mockReturnValue('/mocked/dir/name');
55
}
66

77
/**

src/components/AccountNotifications.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { act, fireEvent, render, screen } from '@testing-library/react';
22
import { mockGitHubCloudAccount, mockSettings } from '../__mocks__/state-mocks';
3-
import { ensureStableEmojis } from '../__mocks__/utils';
3+
import { ensureStableEmojis, mockDirectoryPath } from '../__mocks__/utils';
44
import { AppContext } from '../context/App';
55
import { GroupBy } from '../types';
66
import { mockGitHubNotifications } from '../utils/api/__mocks__/response-mocks';
@@ -14,6 +14,7 @@ jest.mock('./RepositoryNotifications', () => ({
1414
describe('components/AccountNotifications.tsx', () => {
1515
beforeEach(() => {
1616
ensureStableEmojis();
17+
mockDirectoryPath();
1718
});
1819

1920
it('should render itself - group notifications by repositories', () => {

src/components/AllRead.test.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import { render } from '@testing-library/react';
2-
import { ensureStableEmojis } from '../__mocks__/utils';
2+
import { ensureStableEmojis, mockDirectoryPath } from '../__mocks__/utils';
33
import { AllRead } from './AllRead';
44

55
describe('components/AllRead.tsx', () => {
66
beforeEach(() => {
77
ensureStableEmojis();
8+
mockDirectoryPath();
89
});
910

1011
it('should render itself & its children', () => {

src/components/AllRead.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { type FC, useMemo } from 'react';
22
import { Constants } from '../utils/constants';
3+
import { EmojiText } from './EmojiText';
34

45
export const AllRead: FC = () => {
56
const emoji = useMemo(
@@ -12,9 +13,11 @@ export const AllRead: FC = () => {
1213

1314
return (
1415
<div className="flex flex-1 flex-col items-center justify-center bg-white p-4 text-black dark:bg-gray-dark dark:text-white">
15-
<h1 className="mt-2 mb-5 text-5xl">{emoji}</h1>
16+
<div className="mt-2 mb-5 text-5xl">
17+
<EmojiText text={emoji} />
18+
</div>
1619

17-
<h2 className="mb-2 text-xl font-semibold">No new notifications.</h2>
20+
<div className="mb-2 text-xl font-semibold">No new notifications.</div>
1821
</div>
1922
);
2023
};

src/components/EmojiText.test.tsx

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { render } from '@testing-library/react';
2+
import { mockDirectoryPath } from '../__mocks__/utils';
3+
import { EmojiText, type IEmojiText } from './EmojiText';
4+
5+
describe('components/icons/Emoji.tsx', () => {
6+
beforeEach(() => {
7+
mockDirectoryPath();
8+
});
9+
10+
it('should render', () => {
11+
const props: IEmojiText = {
12+
text: '🍺',
13+
};
14+
const tree = render(<EmojiText {...props} />);
15+
expect(tree).toMatchSnapshot();
16+
});
17+
});

src/components/EmojiText.tsx

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
import path from 'node:path';
2+
import twemoji from '@discordapp/twemoji';
3+
import { type FC, useEffect, useRef } from 'react';
4+
import { getDirectoryPath } from '../utils/helpers';
5+
6+
export interface IEmojiText {
7+
text: string;
8+
}
9+
10+
type TwemojiOptions = {
11+
base: string;
12+
size: string;
13+
ext: string;
14+
};
15+
16+
export const EmojiText: FC<IEmojiText> = ({ text }) => {
17+
const ref = useRef(null);
18+
19+
useEffect(() => {
20+
if (ref.current) {
21+
ref.current.innerHTML = twemoji.parse(text, {
22+
folder: 'svg',
23+
ext: '.svg',
24+
callback: (icon: string, options: TwemojiOptions, _variant: string) => {
25+
const source = path.resolve(
26+
getDirectoryPath(),
27+
'../../node_modules/@discordapp/twemoji/dist',
28+
);
29+
30+
return ''.concat(source, '/', options.size, '/', icon, options.ext);
31+
},
32+
});
33+
}
34+
}, [text]);
35+
36+
return <span ref={ref} />;
37+
};

src/components/Oops.test.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
import { render } from '@testing-library/react';
2+
import { mockDirectoryPath } from '../__mocks__/utils';
23
import { Oops } from './Oops';
34

45
describe('components/Oops.tsx', () => {
6+
beforeEach(() => {
7+
mockDirectoryPath();
8+
});
9+
510
it('should render itself & its children', () => {
611
const mockError = {
712
title: 'Error title',

src/components/Oops.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { type FC, useMemo } from 'react';
22
import type { GitifyError } from '../types';
3+
import { EmojiText } from './EmojiText';
34

45
interface IOops {
56
error: GitifyError;
@@ -13,9 +14,11 @@ export const Oops: FC<IOops> = ({ error }: IOops) => {
1314

1415
return (
1516
<div className="flex flex-1 flex-col items-center justify-center p-4">
16-
<h1 className="mt-2 mb-5 text-5xl">{emoji}</h1>
17+
<div className="mt-2 mb-5 text-5xl">
18+
<EmojiText text={`${emoji} foo`} />
19+
</div>
1720

18-
<h2 className="mb-2 text-xl font-semibold">{error.title}</h2>
21+
<div className="mb-2 text-xl font-semibold">{error.title}</div>
1922
{error.descriptions.map((description, i) => {
2023
return (
2124
// biome-ignore lint/suspicious/noArrayIndexKey: using index for key to keep the error constants clean

0 commit comments

Comments
 (0)