diff --git a/packages/presentation/src/components/HTMLViewer.svelte b/packages/presentation/src/components/HTMLViewer.svelte
index 1cd18df40ea..100ebfcc046 100644
--- a/packages/presentation/src/components/HTMLViewer.svelte
+++ b/packages/presentation/src/components/HTMLViewer.svelte
@@ -15,13 +15,21 @@
-
+
diff --git a/packages/presentation/src/components/LiteMessageViewer.svelte b/packages/presentation/src/components/LiteMessageViewer.svelte
index 571c099c6cb..3acfd63304d 100644
--- a/packages/presentation/src/components/LiteMessageViewer.svelte
+++ b/packages/presentation/src/components/LiteMessageViewer.svelte
@@ -16,13 +16,21 @@
import { MarkupNode, markupToJSON } from '@hcengineering/text'
import { Markup } from '@hcengineering/core'
import LiteNode from './markup/lite/LiteNode.svelte'
+ import { loadParseEmojisFunction, ParsedTextWithEmojis } from '@hcengineering/emoji'
+ import { onMount } from 'svelte'
export let message: Markup | MarkupNode
export let colorInherit: boolean = false
$: node = typeof message === 'string' ? markupToJSON(message) : message
+
+ let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
+
+ onMount(async () => {
+ parseEmojisFunction = await loadParseEmojisFunction()
+ })
-
+
diff --git a/packages/presentation/src/components/MessageViewer.svelte b/packages/presentation/src/components/MessageViewer.svelte
index 5eb062b4045..761e4c91d4e 100644
--- a/packages/presentation/src/components/MessageViewer.svelte
+++ b/packages/presentation/src/components/MessageViewer.svelte
@@ -16,6 +16,8 @@
-
+
diff --git a/packages/presentation/src/components/markup/Node.svelte b/packages/presentation/src/components/markup/Node.svelte
index 9344d1da033..432c0f71777 100644
--- a/packages/presentation/src/components/markup/Node.svelte
+++ b/packages/presentation/src/components/markup/Node.svelte
@@ -17,10 +17,12 @@
import NodeMarks from './NodeMarks.svelte'
import NodeContent from './NodeContent.svelte'
+ import { ParsedTextWithEmojis } from '@hcengineering/emoji'
export let node: MarkupNode
- export let single = true
+ export let singleTextNode = false
export let preview = false
+ export let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
{#if node}
@@ -28,9 +30,9 @@
{#if marks.length > 0}
-
+
{:else}
-
+
{/if}
{/if}
diff --git a/packages/presentation/src/components/markup/NodeContent.svelte b/packages/presentation/src/components/markup/NodeContent.svelte
index 7191ff0bbf6..e72b76bd57b 100644
--- a/packages/presentation/src/components/markup/NodeContent.svelte
+++ b/packages/presentation/src/components/markup/NodeContent.svelte
@@ -21,11 +21,14 @@
import MarkdownNode from './MarkdownNode.svelte'
import Node from './Node.svelte'
import { getBlobRef } from '../../preview'
- import { emojiRegex } from '@hcengineering/emoji'
+ import { ParsedTextWithEmojis } from '@hcengineering/emoji'
export let node: MarkupNode
- export let single = true
+ export let singleTextNode = false
export let preview = false
+ export let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
+
+ let parsedTextWithEmojis: ParsedTextWithEmojis | undefined = undefined
function toRefBlob (blobId: AttrValue): Ref {
return blobId as Ref
@@ -54,11 +57,8 @@
return value != null ? (typeof value === 'string' ? parseInt(value) : value) : undefined
}
- const checkEmoji = (nodes: MarkupNode[]): boolean => {
- if (nodes.length !== 1) return false
- const match = nodes[0].text?.match(emojiRegex)
- if (match == null) return false
- return match[0] === nodes[0].text
+ $: if (node.type === MarkupNodeType.text && parseEmojisFunction) {
+ parsedTextWithEmojis = parseEmojisFunction(node.text ?? '')
}
@@ -69,13 +69,37 @@
{#if node.type === MarkupNodeType.doc}
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
{:else if node.type === MarkupNodeType.text}
- {node.text}
+ {#if parsedTextWithEmojis === undefined}
+ {node.text}
+ {:else}
+ {#each parsedTextWithEmojis.nodes as textOrEmoji}
+ {#if typeof textOrEmoji === 'string'}
+ {textOrEmoji}
+ {:else}
+
+ {#if 'image' in textOrEmoji}
+ {@const blob = toRefBlob(textOrEmoji.image)}
+ {@const alt = toString(textOrEmoji.emoji)}
+ {#await getBlobRef(blob) then blobSrc}
+
+ {/await}
+ {:else}
+ {textOrEmoji.emoji}
+ {/if}
+
+ {/if}
+ {/each}
+ {/if}
{:else if node.type === MarkupNodeType.emoji}
-
+
{#if node.attrs?.kind === 'image'}
{@const blob = toRefBlob(attrs.image)}
{@const alt = toString(attrs.emoji)}
@@ -87,10 +111,10 @@
{/if}
{:else if node.type === MarkupNodeType.paragraph}
-
+
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -98,7 +122,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -133,7 +157,7 @@
{:else if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
{:else if node.type === MarkupNodeType.hard_break}
@@ -143,7 +167,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -151,7 +175,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -159,7 +183,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -171,7 +195,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -180,7 +204,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -189,7 +213,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
@@ -199,7 +223,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
|
@@ -209,7 +233,7 @@
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
|
@@ -223,7 +247,7 @@
unknown node: "{node.type}"
{#if nodes.length > 0}
{#each nodes as node}
-
+
{/each}
{/if}
{/if}
diff --git a/packages/presentation/src/components/markup/lite/LiteNode.svelte b/packages/presentation/src/components/markup/lite/LiteNode.svelte
index c7c193015e9..6941805fc56 100644
--- a/packages/presentation/src/components/markup/lite/LiteNode.svelte
+++ b/packages/presentation/src/components/markup/lite/LiteNode.svelte
@@ -17,15 +17,17 @@
import LiteNodeContent from './LiteNodeContent.svelte'
import NodeMarks from '../NodeMarks.svelte'
+ import { ParsedTextWithEmojis } from '@hcengineering/emoji'
export let node: MarkupNode
export let colorInherit: boolean = false
+ export let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
{#if node}
{@const marks = node.marks ?? []}
-
+
{/if}
diff --git a/packages/presentation/src/components/markup/lite/LiteNodeContent.svelte b/packages/presentation/src/components/markup/lite/LiteNodeContent.svelte
index 84d018f054f..f89bda14540 100644
--- a/packages/presentation/src/components/markup/lite/LiteNodeContent.svelte
+++ b/packages/presentation/src/components/markup/lite/LiteNodeContent.svelte
@@ -20,9 +20,13 @@
import ObjectNode from '../ObjectNode.svelte'
import NodeMarks from '../NodeMarks.svelte'
import { getBlobRef } from '../../../preview'
+ import { ParsedTextWithEmojis } from '@hcengineering/emoji'
export let node: MarkupNode
export let colorInherit: boolean = false
+ export let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
+
+ let parsedTextWithEmojis: ParsedTextWithEmojis | undefined = undefined
function toRefBlob (blobId: AttrValue): Ref {
return blobId as Ref
@@ -42,6 +46,10 @@
function toString (value: AttrValue | undefined): string | undefined {
return value != null ? `${value}` : undefined
}
+
+ $: if (node.type === MarkupNodeType.text && parseEmojisFunction) {
+ parsedTextWithEmojis = parseEmojisFunction(node.text ?? '')
+ }
{#if node}
@@ -49,15 +57,35 @@
{@const nodes = node.content ?? []}
{#if node.type === MarkupNodeType.doc}
-
+
{:else if node.type === MarkupNodeType.text}
- {node.text}
+ {#if parsedTextWithEmojis === undefined}
+ {node.text}
+ {:else}
+ {#each parsedTextWithEmojis.nodes as textOrEmoji}
+ {#if typeof textOrEmoji === 'string'}
+ {textOrEmoji}
+ {:else}
+
+ {#if 'image' in textOrEmoji}
+ {@const blob = toRefBlob(textOrEmoji.image)}
+ {@const alt = toString(textOrEmoji.emoji)}
+ {#await getBlobRef(blob) then blobSrc}
+
+ {/await}
+ {:else}
+ {textOrEmoji.emoji}
+ {/if}
+
+ {/if}
+ {/each}
+ {/if}
{:else if node.type === MarkupNodeType.paragraph}
-
+
{:else if node.type === MarkupNodeType.blockquote}
-
+
{:else if node.type === MarkupNodeType.horizontal_rule}
{:else if node.type === MarkupNodeType.code_block}
@@ -70,7 +98,7 @@
}
]}
>
-
+
{:else if node.type === MarkupNodeType.reference}
@@ -81,7 +109,7 @@
{#if objectClass !== undefined && objectId !== undefined}
{:else}
-
+
{/if}
{:else if node.type === MarkupNodeType.emoji}
@@ -101,10 +129,10 @@
{:else if node.type === MarkupNodeType.subLink}
-
+
{:else}
-
+
{/if}
{/if}
diff --git a/packages/presentation/src/components/markup/lite/LiteNodes.svelte b/packages/presentation/src/components/markup/lite/LiteNodes.svelte
index ccee927897f..87d2c9e3a43 100644
--- a/packages/presentation/src/components/markup/lite/LiteNodes.svelte
+++ b/packages/presentation/src/components/markup/lite/LiteNodes.svelte
@@ -16,13 +16,15 @@
import { MarkupNode } from '@hcengineering/text'
import LiteNode from './LiteNode.svelte'
+ import { ParsedTextWithEmojis } from '@hcengineering/emoji'
export let nodes: MarkupNode[]
export let colorInherit: boolean = false
+ export let parseEmojisFunction: ((text: string) => ParsedTextWithEmojis) | undefined = undefined
{#if nodes}
{#each nodes as node}
-
+
{/each}
{/if}
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-0-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-0-400-normal.woff
new file mode 100644
index 00000000000..f6df128c0b9
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-0-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-1-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-1-400-normal.woff
new file mode 100644
index 00000000000..9027a7a4bc6
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-1-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-10-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-10-400-normal.woff
new file mode 100644
index 00000000000..c52bc59fa6c
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-10-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-11-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-11-400-normal.woff
new file mode 100644
index 00000000000..cac257a2e64
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-11-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-2-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-2-400-normal.woff
new file mode 100644
index 00000000000..9c9ae96d0e8
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-2-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-3-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-3-400-normal.woff
new file mode 100644
index 00000000000..dcd5c1364e9
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-3-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-4-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-4-400-normal.woff
new file mode 100644
index 00000000000..e051bd6bbd1
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-4-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-5-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-5-400-normal.woff
new file mode 100644
index 00000000000..c6817da4265
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-5-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-6-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-6-400-normal.woff
new file mode 100644
index 00000000000..e95cce32e80
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-6-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-7-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-7-400-normal.woff
new file mode 100644
index 00000000000..485cffade51
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-7-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-8-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-8-400-normal.woff
new file mode 100644
index 00000000000..8ca4274e801
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-8-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-9-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-9-400-normal.woff
new file mode 100644
index 00000000000..dc2af9d8bb1
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-9-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-emoji-400-normal.woff b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-emoji-400-normal.woff
new file mode 100644
index 00000000000..8be5f8887f8
Binary files /dev/null and b/packages/theme/fonts/complete/woff/noto-color/noto-color-emoji-emoji-400-normal.woff differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-0-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-0-400-normal.woff2
new file mode 100644
index 00000000000..37016bc77dd
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-0-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-1-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-1-400-normal.woff2
new file mode 100644
index 00000000000..b7778aab326
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-1-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-10-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-10-400-normal.woff2
new file mode 100644
index 00000000000..fd7dac278b2
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-10-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-11-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-11-400-normal.woff2
new file mode 100644
index 00000000000..07c5df2fbce
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-11-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-2-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-2-400-normal.woff2
new file mode 100644
index 00000000000..d9b1c0da2f2
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-2-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-3-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-3-400-normal.woff2
new file mode 100644
index 00000000000..464a973ff4e
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-3-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-4-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-4-400-normal.woff2
new file mode 100644
index 00000000000..e6b08ac81d0
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-4-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-5-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-5-400-normal.woff2
new file mode 100644
index 00000000000..6ebd9524b4f
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-5-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-6-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-6-400-normal.woff2
new file mode 100644
index 00000000000..875d7083931
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-6-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-7-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-7-400-normal.woff2
new file mode 100644
index 00000000000..001f13c08bf
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-7-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-8-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-8-400-normal.woff2
new file mode 100644
index 00000000000..07a13bc142a
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-8-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-9-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-9-400-normal.woff2
new file mode 100644
index 00000000000..76e3a15afde
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-9-400-normal.woff2 differ
diff --git a/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-emoji-400-normal.woff2 b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-emoji-400-normal.woff2
new file mode 100644
index 00000000000..971a348f250
Binary files /dev/null and b/packages/theme/fonts/complete/woff2/noto-color/noto-color-emoji-emoji-400-normal.woff2 differ
diff --git a/packages/theme/src/Theme.svelte b/packages/theme/src/Theme.svelte
index c333f424da1..1e2837ffda8 100644
--- a/packages/theme/src/Theme.svelte
+++ b/packages/theme/src/Theme.svelte
@@ -25,15 +25,17 @@
getCurrentTheme,
isSystemThemeDark,
isThemeDark,
- themeStore as themeOptions
+ themeStore as themeOptions,
+ getCurrentEmoji
} from './'
const currentTheme = writable(getCurrentTheme())
const currentFontSize = writable(getCurrentFontSize())
const currentLanguage = writable(getCurrentLanguage())
+ const currentEmoji = writable(getCurrentEmoji())
- const setOptions = (currentFont: string, theme: string, language: string) => {
- themeOptions.set(new ThemeOptions(currentFont === 'normal-font' ? 16 : 14, isThemeDark(theme), language))
+ const setOptions = (currentFont: string, theme: string, language: string, emoji: string) => {
+ themeOptions.set(new ThemeOptions(currentFont === 'normal-font' ? 16 : 14, isThemeDark(theme), language, emoji))
}
const getRealTheme = (theme: string): string => (isThemeDark(theme) ? ThemeVariant.Dark : ThemeVariant.Light)
@@ -42,16 +44,22 @@
if (set) {
localStorage.setItem('theme', theme)
}
- document.documentElement.setAttribute('class', `${getRealTheme(theme)} ${getCurrentFontSize()}`)
- setOptions(getCurrentFontSize(), theme, getCurrentLanguage())
+ document.documentElement.setAttribute(
+ 'class',
+ `${getRealTheme(theme)} ${getCurrentFontSize()} ${getCurrentEmoji()}`
+ )
+ setOptions(getCurrentFontSize(), theme, getCurrentLanguage(), getCurrentEmoji())
}
const setRootFontSize = (fontsize: string, set = true) => {
currentFontSize.set(fontsize)
if (set) {
localStorage.setItem('fontsize', fontsize)
}
- document.documentElement.setAttribute('class', `${getRealTheme(getCurrentTheme())} ${fontsize}`)
- setOptions(fontsize, getCurrentTheme(), getCurrentLanguage())
+ document.documentElement.setAttribute(
+ 'class',
+ `${getRealTheme(getCurrentTheme())} ${fontsize} ${getCurrentEmoji()}`
+ )
+ setOptions(fontsize, getCurrentTheme(), getCurrentLanguage(), getCurrentEmoji())
}
const setLanguage = async (language: string, set: boolean = true) => {
currentLanguage.set(language)
@@ -61,7 +69,18 @@
Analytics.setTag('language', language)
setMetadata(platform.metadata.locale, $currentLanguage)
await loadPluginStrings($currentLanguage, set)
- setOptions(getCurrentFontSize(), getCurrentTheme(), language)
+ setOptions(getCurrentFontSize(), getCurrentTheme(), language, getCurrentEmoji())
+ }
+ const setEmoji = (emoji: string, set = true) => {
+ currentEmoji.set(emoji)
+ if (set) {
+ localStorage.setItem('emoji', emoji)
+ }
+ document.documentElement.setAttribute(
+ 'class',
+ `${getRealTheme(getCurrentTheme())} ${getCurrentFontSize()} ${emoji}`
+ )
+ setOptions(getCurrentFontSize(), getCurrentTheme(), getCurrentLanguage(), emoji)
}
setContext('theme', {
@@ -76,6 +95,10 @@
currentLanguage,
setLanguage
})
+ setContext('emoji', {
+ currentEmoji,
+ setEmoji
+ })
let remove: any = null
diff --git a/packages/theme/src/index.ts b/packages/theme/src/index.ts
index 92ca514f894..ef98ab74887 100644
--- a/packages/theme/src/index.ts
+++ b/packages/theme/src/index.ts
@@ -62,13 +62,18 @@ export const getCurrentLanguage = (): string => {
Analytics.setTag('language', lang)
return lang
}
+/**
+ * @public
+ */
+export const getCurrentEmoji = (): string => localStorage.getItem('emoji') ?? getDefaultProps('emoji', 'emoji-system')
export class ThemeOptions {
readonly variant: ThemeVariantType
constructor (
readonly fontSize: number,
readonly dark: boolean,
- readonly language: string
+ readonly language: string,
+ readonly emoji: string
) {
this.variant = dark ? ThemeVariant.Dark : ThemeVariant.Light
}
@@ -80,7 +85,8 @@ export function initThemeStore (): void {
new ThemeOptions(
getCurrentFontSize() === 'normal-font' ? 16 : 14,
isThemeDark(getCurrentTheme()),
- getCurrentLanguage()
+ getCurrentLanguage(),
+ getCurrentEmoji()
)
)
}
diff --git a/packages/theme/styles/common.scss b/packages/theme/styles/common.scss
index b9b1e3ab5e7..5d028df294a 100644
--- a/packages/theme/styles/common.scss
+++ b/packages/theme/styles/common.scss
@@ -874,6 +874,14 @@
.message.outcoming { border-radius: 0.75rem 0.125rem 0.125rem 0.75rem; }
}
+.emoji-system {}
+
+.emoji-noto {
+ .emoji {
+ font-family: "Noto Color Emoji";
+ }
+}
+
.emoji {
&.center {
display: flex;
@@ -897,4 +905,4 @@
.emoji.fitSize > img {
height: 1em;
-}
\ No newline at end of file
+}
diff --git a/packages/theme/styles/global.scss b/packages/theme/styles/global.scss
index 793cfa3086e..8e2f2b7eabb 100644
--- a/packages/theme/styles/global.scss
+++ b/packages/theme/styles/global.scss
@@ -33,6 +33,7 @@
@import "./love.scss";
@import "./mono.scss";
+@import "./noto-color.scss";
@font-face {
font-family: 'IBM Plex Sans';
diff --git a/packages/theme/styles/noto-color.scss b/packages/theme/styles/noto-color.scss
new file mode 100644
index 00000000000..34a472e3e9c
--- /dev/null
+++ b/packages/theme/styles/noto-color.scss
@@ -0,0 +1,120 @@
+/* noto-color-emoji-[0]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-0-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-0-400-normal.woff') format('woff');
+ unicode-range: U+1f1e6-1f1ff;
+}
+
+/* noto-color-emoji-[1]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-1-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-1-400-normal.woff') format('woff');
+ unicode-range: U+200d,U+2620,U+26a7,U+fe0f,U+1f308,U+1f38c,U+1f3c1,U+1f3f3-1f3f4,U+1f6a9,U+e0062-e0063,U+e0065,U+e0067,U+e006c,U+e006e,U+e0073-e0074,U+e0077,U+e007f;
+}
+
+/* noto-color-emoji-[2]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-2-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-2-400-normal.woff') format('woff');
+ unicode-range: U+23,U+2a,U+30-39,U+a9,U+ae,U+200d,U+203c,U+2049,U+20e3,U+2122,U+2139,U+2194-2199,U+21a9-21aa,U+23cf,U+23e9-23ef,U+23f8-23fa,U+24c2,U+25aa-25ab,U+25b6,U+25c0,U+25fb-25fe,U+2611,U+2622-2623,U+2626,U+262a,U+262e-262f,U+2638,U+2640,U+2642,U+2648-2653,U+2660,U+2663,U+2665-2666,U+2668,U+267b,U+267e-267f,U+2695,U+269b-269c,U+26a0,U+26a7,U+26aa-26ab,U+26ce,U+26d4,U+2705,U+2714,U+2716,U+271d,U+2721,U+2733-2734,U+2747,U+274c,U+274e,U+2753-2755,U+2757,U+2764,U+2795-2797,U+27a1,U+27b0,U+27bf,U+2934-2935,U+2b05-2b07,U+2b1b-2b1c,U+2b55,U+3030,U+303d,U+3297,U+3299,U+fe0f,U+1f170-1f171,U+1f17e-1f17f,U+1f18e,U+1f191-1f19a,U+1f201-1f202,U+1f21a,U+1f22f,U+1f232-1f23a,U+1f250-1f251,U+1f310,U+1f3a6,U+1f3b5-1f3b6,U+1f3bc,U+1f3e7,U+1f441,U+1f499-1f49c,U+1f49f-1f4a0,U+1f4a2,U+1f4ac-1f4ad,U+1f4b1-1f4b2,U+1f4b9,U+1f4db,U+1f4f2-1f4f6,U+1f500-1f50a,U+1f515,U+1f518-1f524,U+1f52f-1f53d,U+1f549,U+1f54e,U+1f5a4,U+1f5e8,U+1f5ef,U+1f6ab,U+1f6ad-1f6b1,U+1f6b3,U+1f6b7-1f6bc,U+1f6be,U+1f6c2-1f6c5,U+1f6d0-1f6d1,U+1f6d7,U+1f6dc,U+1f7e0-1f7eb,U+1f7f0,U+1f90d-1f90e,U+1f9e1,U+1fa75-1fa77,U+1faaf;
+}
+
+/* noto-color-emoji-[3]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-3-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-3-400-normal.woff') format('woff');
+ unicode-range: U+231a-231b,U+2328,U+23f0-23f3,U+2602,U+260e,U+2692,U+2694,U+2696-2697,U+2699,U+26b0-26b1,U+26cf,U+26d1,U+26d3,U+2702,U+2709,U+270f,U+2712,U+fe0f,U+1f302,U+1f321,U+1f392-1f393,U+1f3a9,U+1f3bd,U+1f3ee,U+1f3f7,U+1f3fa,U+1f451-1f462,U+1f484,U+1f489-1f48a,U+1f48c-1f48e,U+1f4a1,U+1f4a3,U+1f4b0,U+1f4b3-1f4b8,U+1f4bb-1f4da,U+1f4dc-1f4f1,U+1f4ff,U+1f50b-1f514,U+1f516-1f517,U+1f526-1f529,U+1f52c-1f52e,U+1f550-1f567,U+1f56f-1f570,U+1f576,U+1f587,U+1f58a-1f58d,U+1f5a5,U+1f5a8,U+1f5b1-1f5b2,U+1f5c2-1f5c4,U+1f5d1-1f5d3,U+1f5dc-1f5de,U+1f5e1,U+1f5f3,U+1f6aa,U+1f6ac,U+1f6bd,U+1f6bf,U+1f6c1,U+1f6cb,U+1f6cd-1f6cf,U+1f6d2,U+1f6e0-1f6e1,U+1f6f0,U+1f97b-1f97f,U+1f9af,U+1f9ba,U+1f9e2-1f9e6,U+1f9ea-1f9ec,U+1f9ee-1f9f4,U+1f9f7-1f9ff,U+1fa71-1fa74,U+1fa79-1fa7b,U+1fa86,U+1fa91-1fa93,U+1fa96,U+1fa99-1faa0,U+1faa2-1faa7,U+1faaa-1faae;
+}
+
+/* noto-color-emoji-[4]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-4-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-4-400-normal.woff') format('woff');
+ unicode-range: U+265f,U+26bd-26be,U+26f3,U+26f8,U+fe0f,U+1f004,U+1f0cf,U+1f380-1f384,U+1f386-1f38b,U+1f38d-1f391,U+1f396-1f397,U+1f399-1f39b,U+1f39e-1f39f,U+1f3a3-1f3a5,U+1f3a7-1f3a9,U+1f3ab-1f3b4,U+1f3b7-1f3bb,U+1f3bd-1f3c0,U+1f3c5-1f3c6,U+1f3c8-1f3c9,U+1f3cf-1f3d3,U+1f3f8-1f3f9,U+1f47e,U+1f4e2,U+1f4f7-1f4fd,U+1f52b,U+1f579,U+1f58c-1f58d,U+1f5bc,U+1f6f7,U+1f6f9,U+1f6fc,U+1f93f,U+1f941,U+1f945,U+1f947-1f94f,U+1f9e7-1f9e9,U+1f9f5-1f9f6,U+1fa70-1fa71,U+1fa80-1fa81,U+1fa83-1fa85,U+1fa87-1fa88,U+1fa94-1fa95,U+1fa97-1fa98,U+1faa1,U+1faa9;
+}
+
+/* noto-color-emoji-[5]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-5-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-5-400-normal.woff') format('woff');
+ unicode-range: U+2693,U+26e9-26ea,U+26f1-26f2,U+26f4-26f5,U+26fa,U+26fd,U+2708,U+fe0f,U+1f301,U+1f303,U+1f306-1f307,U+1f309,U+1f310,U+1f3a0-1f3a2,U+1f3aa,U+1f3cd-1f3ce,U+1f3d5,U+1f3d7-1f3db,U+1f3df-1f3e6,U+1f3e8-1f3ed,U+1f3ef-1f3f0,U+1f488,U+1f492,U+1f4ba,U+1f54b-1f54d,U+1f5fa-1f5ff,U+1f680-1f6a2,U+1f6a4-1f6a8,U+1f6b2,U+1f6d1,U+1f6d5-1f6d6,U+1f6dd-1f6df,U+1f6e2-1f6e5,U+1f6e9,U+1f6eb-1f6ec,U+1f6f3-1f6f6,U+1f6f8,U+1f6fa-1f6fb,U+1f9bc-1f9bd,U+1f9ed,U+1f9f3,U+1fa7c;
+}
+
+/* noto-color-emoji-[6]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-6-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-6-400-normal.woff') format('woff');
+ unicode-range: U+2615,U+fe0f,U+1f32d-1f330,U+1f336,U+1f33d,U+1f345-1f37f,U+1f382,U+1f52a,U+1f942-1f944,U+1f950-1f96f,U+1f99e,U+1f9aa,U+1f9c0-1f9cb,U+1fad0-1fadb;
+}
+
+/* noto-color-emoji-[7]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-7-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-7-400-normal.woff') format('woff');
+ unicode-range: U+200d,U+2600-2601,U+2603-2604,U+2614,U+2618,U+26a1,U+26c4-26c5,U+26c8,U+26f0,U+2728,U+2744,U+2b1b,U+2b50,U+fe0f,U+1f300,U+1f304-1f305,U+1f308,U+1f30a-1f30f,U+1f311-1f321,U+1f324-1f32c,U+1f331-1f335,U+1f337-1f33c,U+1f33e-1f344,U+1f3d4,U+1f3d6,U+1f3dc-1f3de,U+1f3f5,U+1f400-1f43f,U+1f490,U+1f4a7,U+1f4ab,U+1f4ae,U+1f525,U+1f54a,U+1f573,U+1f577-1f578,U+1f648-1f64a,U+1f940,U+1f980-1f9ae,U+1f9ba,U+1fa90,U+1faa8,U+1fab0-1fabd,U+1fabf,U+1face-1facf,U+1fae7;
+}
+
+/* noto-color-emoji-[8]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-8-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-8-400-normal.woff') format('woff');
+ unicode-range: U+200d,U+2640,U+2642,U+2695-2696,U+26f7,U+26f9,U+2708,U+2764,U+fe0f,U+1f33e,U+1f373,U+1f37c,U+1f384-1f385,U+1f393,U+1f3a4,U+1f3a8,U+1f3c2-1f3c4,U+1f3c7,U+1f3ca-1f3cc,U+1f3eb,U+1f3ed,U+1f3fb-1f3ff,U+1f466-1f478,U+1f47c,U+1f481-1f483,U+1f486-1f487,U+1f48b,U+1f48f,U+1f491,U+1f4bb-1f4bc,U+1f527,U+1f52c,U+1f574-1f575,U+1f57a,U+1f645-1f647,U+1f64b,U+1f64d-1f64e,U+1f680,U+1f692,U+1f6a3,U+1f6b4-1f6b6,U+1f6c0,U+1f6cc,U+1f91d,U+1f926,U+1f930-1f931,U+1f934-1f93a,U+1f93c-1f93e,U+1f977,U+1f9af-1f9b3,U+1f9b8-1f9b9,U+1f9bc-1f9bd,U+1f9cc-1f9cf,U+1f9d1-1f9df,U+1fa82,U+1fac3-1fac5;
+}
+
+/* noto-color-emoji-[9]-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-9-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-9-400-normal.woff') format('woff');
+ unicode-range: U+200d,U+261d,U+2620,U+2639-263a,U+2665,U+270a-270d,U+2728,U+2763-2764,U+2b50,U+fe0f,U+1f31a-1f31f,U+1f32b,U+1f383,U+1f389,U+1f3fb-1f3ff,U+1f440-1f450,U+1f463-1f465,U+1f479-1f47b,U+1f47d-1f480,U+1f485,U+1f48b-1f48c,U+1f493-1f49f,U+1f4a4-1f4a6,U+1f4a8-1f4ab,U+1f4af,U+1f525,U+1f573,U+1f590,U+1f595-1f596,U+1f5a4,U+1f5e3,U+1f600-1f644,U+1f648-1f64a,U+1f64c,U+1f64f,U+1f90c-1f925,U+1f927-1f92f,U+1f932-1f933,U+1f970-1f976,U+1f978-1f97a,U+1f9a0,U+1f9b4-1f9b7,U+1f9bb,U+1f9be-1f9bf,U+1f9d0,U+1f9e0-1f9e1,U+1fa75-1fa79,U+1fac0-1fac2,U+1fae0-1fae6,U+1fae8,U+1faf0-1faf8;
+}
+
+/* noto-color-emoji-emoji-400-normal */
+@font-face {
+ font-family: 'Noto Color Emoji';
+ font-style: normal;
+ font-display: swap;
+ font-weight: 400;
+ src: url('../fonts/complete/woff2/noto-color/noto-color-emoji-emoji-400-normal.woff2') format('woff2'),
+ url('../fonts/complete/woff/noto-color/noto-color-emoji-emoji-400-normal.woff') format('woff');
+ unicode-range: U+200D,U+203C,U+2049,U+20E3,U+2139,U+2194-2199,U+21A9-21AA,U+231A-231B,U+2328,U+23CF,U+23E9-23F3,U+23F8-23FA,U+24C2,U+25AA-25AB,U+25B6,U+25C0,U+25FB-25FE,U+2600-2604,U+260E,U+2611,U+2614-2615,U+2618,U+261D,U+2620,U+2622-2623,U+2626,U+262A,U+262E-262F,U+2638-263A,U+2640,U+2642,U+2648-2653,U+265F-2660,U+2663,U+2665-2666,U+2668,U+267B,U+267E-267F,U+2692-2697,U+2699,U+269B-269C,U+26A0-26A1,U+26A7,U+26AA-26AB,U+26B0-26B1,U+26BD-26BE,U+26C4-26C5,U+26C8,U+26CE-26CF,U+26D1,U+26D3-26D4,U+26E9-26EA,U+26F0-26F5,U+26F7-26FA,U+26FD,U+2702,U+2705,U+2708-270D,U+270F,U+2712,U+2714,U+2716,U+271D,U+2721,U+2728,U+2733-2734,U+2744,U+2747,U+274C,U+274E,U+2753-2755,U+2757,U+2763-2764,U+2795-2797,U+27A1,U+27B0,U+27BF,U+2934-2935,U+2B05-2B07,U+2B1B-2B1C,U+2B50,U+2B55,U+3030,U+303D,U+3297,U+3299,U+FE0F,U+1F004,U+1F0CF,U+1F170-1F171,U+1F17E-1F17F,U+1F18E,U+1F191-1F19A,U+1F1E6-1F1FF,U+1F201-1F202,U+1F21A,U+1F22F,U+1F232-1F23A,U+1F250-1F251,U+1F300-1F321,U+1F324-1F393,U+1F396-1F397,U+1F399-1F39B,U+1F39E-1F3F0,U+1F3F3-1F3F5,U+1F3F7-1F4FD,U+1F4FF-1F53D,U+1F549-1F54E,U+1F550-1F567,U+1F56F-1F570,U+1F573-1F57A,U+1F587,U+1F58A-1F58D,U+1F590,U+1F595-1F596,U+1F5A4-1F5A5,U+1F5A8,U+1F5B1-1F5B2,U+1F5BC,U+1F5C2-1F5C4,U+1F5D1-1F5D3,U+1F5DC-1F5DE,U+1F5E1,U+1F5E3,U+1F5E8,U+1F5EF,U+1F5F3,U+1F5FA-1F64F,U+1F680-1F6C5,U+1F6CB-1F6D2,U+1F6D5-1F6D7,U+1F6DC-1F6E5,U+1F6E9,U+1F6EB-1F6EC,U+1F6F0,U+1F6F3-1F6FC,U+1F7E0-1F7EB,U+1F7F0,U+1F90C-1F93A,U+1F93C-1F945,U+1F947-1F9FF,U+1FA70-1FA7C,U+1FA80-1FA88,U+1FA90-1FABD,U+1FABF-1FAC5,U+1FACE-1FADB,U+1FAE0-1FAE8,U+1FAF0-1FAF8,U+E0062-E0063,U+E0065,U+E0067,U+E006C,U+E006E,U+E0073-E0074,U+E0077,U+E007F,U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+2074,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD;
+}
\ No newline at end of file
diff --git a/packages/ui/lang/cs.json b/packages/ui/lang/cs.json
index c79e6d4da83..704862577a5 100644
--- a/packages/ui/lang/cs.json
+++ b/packages/ui/lang/cs.json
@@ -103,6 +103,9 @@
"Yesterday": "Včera",
"ThisWeek": "Tento týden",
"ThisMonth": "Tento měsíc",
- "ThisYear": "Tento rok"
+ "ThisYear": "Tento rok",
+ "EmojiStyle": "Styl emoji",
+ "EmojiSystem": "Výchozí systémové",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/de.json b/packages/ui/lang/de.json
index a13bfe536fb..55d8a0d147b 100644
--- a/packages/ui/lang/de.json
+++ b/packages/ui/lang/de.json
@@ -104,6 +104,9 @@
"Yesterday": "Gestern",
"ThisWeek": "Diese Woche",
"ThisMonth": "Diesen Monat",
- "ThisYear": "Dieses Jahr"
+ "ThisYear": "Dieses Jahr",
+ "EmojiStyle": "Emoji-Stil",
+ "EmojiSystem": "Systemstandard",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/en.json b/packages/ui/lang/en.json
index f14b341ecaf..a7f6282a175 100644
--- a/packages/ui/lang/en.json
+++ b/packages/ui/lang/en.json
@@ -104,6 +104,9 @@
"Yesterday": "Yesterday",
"ThisWeek": "This week",
"ThisMonth": "This month",
- "ThisYear": "This year"
+ "ThisYear": "This year",
+ "EmojiStyle": "Emoji Style",
+ "EmojiSystem": "System Default",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/es.json b/packages/ui/lang/es.json
index ffab90004ed..1f8fece65e5 100644
--- a/packages/ui/lang/es.json
+++ b/packages/ui/lang/es.json
@@ -104,6 +104,9 @@
"Yesterday": "Ayer",
"ThisWeek": "Esta semana",
"ThisMonth": "Este mes",
- "ThisYear": "Este año"
+ "ThisYear": "Este año",
+ "EmojiStyle": "Estilo de emoji",
+ "EmojiSystem": "Predeterminado del sistema",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/fr.json b/packages/ui/lang/fr.json
index 5b6a329e123..5081fc70bee 100644
--- a/packages/ui/lang/fr.json
+++ b/packages/ui/lang/fr.json
@@ -104,6 +104,9 @@
"Yesterday": "Hier",
"ThisWeek": "Cette semaine",
"ThisMonth": "Ce mois-ci",
- "ThisYear": "Cette année"
+ "ThisYear": "Cette année",
+ "EmojiStyle": "Style d'émoji",
+ "EmojiSystem": "Par défaut du système",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/it.json b/packages/ui/lang/it.json
index 7ea036dc094..15c212ddba4 100644
--- a/packages/ui/lang/it.json
+++ b/packages/ui/lang/it.json
@@ -104,6 +104,9 @@
"Yesterday": "Ieri",
"ThisWeek": "Questa settimana",
"ThisMonth": "Questo mese",
- "ThisYear": "Quest'anno"
+ "ThisYear": "Quest'anno",
+ "EmojiStyle": "Stile emoji",
+ "EmojiSystem": "Predefinito di sistema",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/ja.json b/packages/ui/lang/ja.json
index ad16111fd41..c6d9531c155 100644
--- a/packages/ui/lang/ja.json
+++ b/packages/ui/lang/ja.json
@@ -104,6 +104,9 @@
"Yesterday": "昨日",
"ThisWeek": "今週",
"ThisMonth": "今月",
- "ThisYear": "今年"
+ "ThisYear": "今年",
+ "EmojiStyle": "絵文字スタイル",
+ "EmojiSystem": "システムデフォルト",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/pt.json b/packages/ui/lang/pt.json
index 53a85bcda86..8e08ad8965c 100644
--- a/packages/ui/lang/pt.json
+++ b/packages/ui/lang/pt.json
@@ -104,6 +104,9 @@
"Yesterday": "Ontem",
"ThisWeek": "Esta semana",
"ThisMonth": "Este mês",
- "ThisYear": "Este ano"
+ "ThisYear": "Este ano",
+ "EmojiStyle": "Estilo de emoji",
+ "EmojiSystem": "Padrão do sistema",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/ru.json b/packages/ui/lang/ru.json
index 5b26730e3bf..081716b7b24 100644
--- a/packages/ui/lang/ru.json
+++ b/packages/ui/lang/ru.json
@@ -104,6 +104,9 @@
"Yesterday": "Вчера",
"ThisWeek": "Эта неделя",
"ThisMonth": "Этот месяц",
- "ThisYear": "Этот год"
+ "ThisYear": "Этот год",
+ "EmojiStyle": "Стиль эмодзи",
+ "EmojiSystem": "Системный по умолчанию",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/lang/zh.json b/packages/ui/lang/zh.json
index 194607157dc..0cab25fd23c 100644
--- a/packages/ui/lang/zh.json
+++ b/packages/ui/lang/zh.json
@@ -104,6 +104,9 @@
"Yesterday": "昨天",
"ThisWeek": "本周",
"ThisMonth": "本月",
- "ThisYear": "今年"
+ "ThisYear": "今年",
+ "EmojiStyle": "表情样式",
+ "EmojiSystem": "系统默认",
+ "EmojiNoto": "Noto Color"
}
}
diff --git a/packages/ui/src/components/internal/SettingsPopup.svelte b/packages/ui/src/components/internal/SettingsPopup.svelte
index 30344b0b9c5..d89e47a5eb4 100644
--- a/packages/ui/src/components/internal/SettingsPopup.svelte
+++ b/packages/ui/src/components/internal/SettingsPopup.svelte
@@ -31,6 +31,7 @@
modalStore,
eventToHTMLElement
} from '../..'
+ import EmojiStyle from './icons/EmojiStyle.svelte'
const { currentFontSize, setFontSize } = getContext<{
currentFontSize: Readable
@@ -46,6 +47,11 @@
setLanguage: (language: string) => void
}>('lang')
+ const { currentEmoji, setEmoji } = getContext<{
+ currentEmoji: Readable
+ setEmoji: (emoji: string) => void
+ }>('emoji')
+
const fontsizes: Array<{ id: string, label: IntlString, size: number }> = [
{ id: 'normal-font', label: ui.string.Spacious, size: 16 },
{ id: 'small-font', label: ui.string.Compact, size: 14 }
@@ -57,6 +63,11 @@
{ id: 'theme-system', label: ui.string.ThemeSystem }
]
+ const emojis: Array<{ id: string, label: IntlString }> = [
+ { id: 'emoji-system', label: ui.string.EmojiSystem },
+ { id: 'emoji-noto', label: ui.string.EmojiNoto }
+ ]
+
const uiLangs = new Set(getMetadata(ui.metadata.Languages))
const langs = [
{ id: 'en', label: ui.string.English, logo: '🇺🇸' },
@@ -99,9 +110,15 @@
setLanguage(language)
}
+ function selectEmoji (emoji: string): void {
+ if ($currentEmoji === emoji) return
+ setEmoji(emoji)
+ }
+
$: $deviceInfo.theme = $currentTheme
$: fontsize = fontsizes.find((fs) => fs.id === $currentFontSize) ?? fontsizes[0]
$: language = langs.find((lang) => lang.id === $currentLanguage) ?? langs[0]
+ $: emoji = emojis.find((e) => e.id === $currentEmoji) ?? emojis[0]
- {skin.emoji}
+ {skin.emoji}
{#if label}{/if}
{#if disabled}{/if}
diff --git a/plugins/emoji-resources/src/components/SkinToneTooltip.svelte b/plugins/emoji-resources/src/components/SkinToneTooltip.svelte
index b00f9ac6e29..13b080e8a55 100644
--- a/plugins/emoji-resources/src/components/SkinToneTooltip.svelte
+++ b/plugins/emoji-resources/src/components/SkinToneTooltip.svelte
@@ -35,7 +35,7 @@
closeTooltip()
}}
>
- {skin.emoji}
+ {skin.emoji}
{/each}
diff --git a/plugins/emoji-resources/src/index.ts b/plugins/emoji-resources/src/index.ts
index 9e6f04bd47e..c9d3edd9bb7 100644
--- a/plugins/emoji-resources/src/index.ts
+++ b/plugins/emoji-resources/src/index.ts
@@ -2,7 +2,7 @@ import type { Resources } from '@hcengineering/platform'
import EmojiPopup from './components/EmojiPopup.svelte'
import SettingsEmojiTable from './components/settings/SettingsEmojiTable.svelte'
import WorkbenchExtension from './components/WorkbenchExtension.svelte'
-import { getCustomEmoji, getEmojiByEmoticon, getEmojiByShortCode } from './utils'
+import { getCustomEmoji, getEmojiByEmoticon, getEmojiByShortCode, parseTextWithEmojis } from './utils'
export { default as EmojiPresenter } from './components/EmojiPresenter.svelte'
@@ -17,6 +17,7 @@ export default async (): Promise => ({
functions: {
GetEmojiByEmoticon: getEmojiByEmoticon,
GetEmojiByShortCode: getEmojiByShortCode,
- GetCustomEmoji: getCustomEmoji
+ GetCustomEmoji: getCustomEmoji,
+ ParseTextWithEmojis: parseTextWithEmojis
}
})
diff --git a/plugins/emoji-resources/src/utils.ts b/plugins/emoji-resources/src/utils.ts
index 596eceb0438..0cb6984ddef 100644
--- a/plugins/emoji-resources/src/utils.ts
+++ b/plugins/emoji-resources/src/utils.ts
@@ -1,5 +1,13 @@
-import { isCustomEmoji, fetchEmojis, fetchMessages } from '@hcengineering/emoji'
-import type { EmojiWithGroup, ExtendedEmoji, Locale, Emoji, CustomEmoji } from '@hcengineering/emoji'
+import { emojiGlobalRegex, shortcodeGlobalRegex, isCustomEmoji, fetchEmojis, fetchMessages } from '@hcengineering/emoji'
+import type {
+ EmojiWithGroup,
+ ExtendedEmoji,
+ Locale,
+ Emoji,
+ CustomEmoji,
+ TextOrEmoji,
+ ParsedTextWithEmojis
+} from '@hcengineering/emoji'
import { emojiCategories } from './types'
import { unicodeEmojiStore, customEmojiStore, getSkinTone } from './store'
import { get } from 'svelte/store'
@@ -109,3 +117,43 @@ export function getEmojiSkins (emoji: ExtendedEmoji): Emoji.Emoji[] | undefined
if (isCustomEmoji(emoji)) return undefined
return emoji.skins
}
+
+export function parseTextWithEmojis (text: string): ParsedTextWithEmojis {
+ const matches = [...text.matchAll(emojiGlobalRegex), ...text.matchAll(shortcodeGlobalRegex)]
+ if (matches.length === 0) return { nodes: [text], emojisOnly: false }
+ matches.sort((a, b) => a.index - b.index)
+
+ const nodes: TextOrEmoji[] = []
+ let emojisOnly: boolean = true
+
+ const pushNode = (node: TextOrEmoji): void => {
+ if (typeof node === 'string') {
+ if (node !== '') {
+ emojisOnly = false
+ nodes.push(node)
+ }
+ } else {
+ nodes.push(node)
+ }
+ }
+
+ let startIndex = 0
+ for (let index = 0; index < matches.length; index++) {
+ const matchStart = matches[index].index
+ pushNode(text.substring(startIndex, matchStart))
+ startIndex = matchStart + matches[index][0].length
+ const emojiText = text.substring(matches[index].index, startIndex)
+ if (emojiText.startsWith(':')) {
+ const customEmoji = getCustomEmoji(emojiText)
+ if (customEmoji === undefined) {
+ pushNode(emojiText)
+ } else {
+ pushNode({ emoji: emojiText, image: customEmoji.image })
+ }
+ } else {
+ pushNode({ emoji: emojiText })
+ }
+ }
+ pushNode(text.substring(startIndex, text.length))
+ return { nodes, emojisOnly }
+}
diff --git a/plugins/emoji/src/plugin.ts b/plugins/emoji/src/plugin.ts
index 27989daf26f..bc38994a4fc 100644
--- a/plugins/emoji/src/plugin.ts
+++ b/plugins/emoji/src/plugin.ts
@@ -15,7 +15,7 @@
import { Asset, type IntlString, plugin, type Plugin, Resource } from '@hcengineering/platform'
import { AnyComponent } from '@hcengineering/ui'
import type { Class, Ref, Doc } from '@hcengineering/core'
-import { CustomEmoji, ExtendedEmoji } from './types'
+import { CustomEmoji, ExtendedEmoji, ParsedTextWithEmojis } from './types'
/** @public */
export const emojiId = 'emoji' as Plugin
@@ -90,7 +90,8 @@ export const emojiPlugin = plugin(emojiId, {
GetEmojiByShortCode: '' as Resource<
(shortcode: string | undefined, skinTone?: number) => ExtendedEmoji | undefined
>,
- GetCustomEmoji: '' as Resource<(shortcode: string | undefined, skinTone?: number) => CustomEmoji | undefined>
+ GetCustomEmoji: '' as Resource<(shortcode: string | undefined, skinTone?: number) => CustomEmoji | undefined>,
+ ParseTextWithEmojis: '' as Resource<(text: string) => ParsedTextWithEmojis>
}
})
diff --git a/plugins/emoji/src/types.ts b/plugins/emoji/src/types.ts
index 22f814becc3..bde8a69068c 100644
--- a/plugins/emoji/src/types.ts
+++ b/plugins/emoji/src/types.ts
@@ -18,6 +18,13 @@ import type { Blob, Doc, Ref } from '@hcengineering/core'
export { default as Emoji } from 'emojibase'
export type ExtendedEmoji = Emoji | CustomEmoji
export type EmojiWithGroup = ExtendedEmoji & { key: string }
+export type TextOrEmoji = string | { emoji: string } | { emoji: string, image: Ref }
+
+/** @public */
+export interface ParsedTextWithEmojis {
+ nodes: TextOrEmoji[]
+ emojisOnly: boolean
+}
/** @public */
export interface CustomEmoji extends Doc {
diff --git a/plugins/emoji/src/utils.ts b/plugins/emoji/src/utils.ts
index 2c313a80d2a..6e52bdcba88 100644
--- a/plugins/emoji/src/utils.ts
+++ b/plugins/emoji/src/utils.ts
@@ -27,6 +27,9 @@ import {
type MessagesDataset,
type ShortcodesDataset
} from 'emojibase'
+import emojiPlugin from './plugin'
+import { getResource } from '@hcengineering/platform'
+import { ParsedTextWithEmojis } from './types'
export const emojiRegex = new RegExp(`(?:^|\\s)(${EMOJI_REGEX.source})$`)
export const emojiGlobalRegex = new RegExp(EMOJI_REGEX.source, EMOJI_REGEX.flags + 'g')
@@ -69,4 +72,13 @@ async function fetchMessages (locale: Locale, options?: FetchFromCDNOptions): Pr
}
}
-export { fetchEmojis, fetchMessages, type Locale }
+async function loadParseEmojisFunction (): Promise<((text: string) => ParsedTextWithEmojis) | undefined> {
+ try {
+ return await getResource(emojiPlugin.functions.ParseTextWithEmojis)
+ } catch (e) {
+ console.log('Cannot locate emoji parsing function')
+ return undefined
+ }
+}
+
+export { fetchEmojis, fetchMessages, loadParseEmojisFunction, type Locale }