mirror of
https://github.com/owncast/owncast.git
synced 2024-10-10 19:16:02 +00:00
../
First pass at the emoji picker
This commit is contained in:
parent
1d213b71d4
commit
8ed01ed4da
@ -14,8 +14,10 @@ import (
|
|||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var emojiCache = make([]models.CustomEmoji, 0)
|
var (
|
||||||
var emojiCacheTimestamp time.Time
|
emojiCache = make([]models.CustomEmoji, 0)
|
||||||
|
emojiCacheTimestamp time.Time
|
||||||
|
)
|
||||||
|
|
||||||
// getCustomEmojiList returns a list of custom emoji either from the cache or from the emoji directory.
|
// getCustomEmojiList returns a list of custom emoji either from the cache or from the emoji directory.
|
||||||
func getCustomEmojiList() []models.CustomEmoji {
|
func getCustomEmojiList() []models.CustomEmoji {
|
||||||
@ -38,7 +40,7 @@ func getCustomEmojiList() []models.CustomEmoji {
|
|||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
name := strings.TrimSuffix(f.Name(), path.Ext(f.Name()))
|
name := strings.TrimSuffix(f.Name(), path.Ext(f.Name()))
|
||||||
emojiPath := filepath.Join(config.EmojiDir, f.Name())
|
emojiPath := filepath.Join(config.EmojiDir, f.Name())
|
||||||
singleEmoji := models.CustomEmoji{Name: name, Emoji: emojiPath}
|
singleEmoji := models.CustomEmoji{Name: name, URL: emojiPath}
|
||||||
emojiCache = append(emojiCache, singleEmoji)
|
emojiCache = append(emojiCache, singleEmoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,6 @@ package models
|
|||||||
|
|
||||||
// CustomEmoji represents an image that can be used in chat as a custom emoji.
|
// CustomEmoji represents an image that can be used in chat as a custom emoji.
|
||||||
type CustomEmoji struct {
|
type CustomEmoji struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Emoji string `json:"emoji"`
|
URL string `json:"url"`
|
||||||
}
|
}
|
||||||
|
@ -120,16 +120,17 @@ export default function ChatTextField(props: Props) {
|
|||||||
|
|
||||||
const handleChange = () => {};
|
const handleChange = () => {};
|
||||||
|
|
||||||
const handleEmojiSelect = emoji => {
|
const handleEmojiSelect = e => {
|
||||||
console.log(emoji);
|
ReactEditor.focus(editor);
|
||||||
if (!emoji.native) {
|
|
||||||
|
if (e.url) {
|
||||||
// Custom emoji
|
// Custom emoji
|
||||||
const { src } = emoji;
|
const { url } = e;
|
||||||
insertImage(editor, src);
|
insertImage(editor, url);
|
||||||
} else {
|
} else {
|
||||||
// Native emoji
|
// Native emoji
|
||||||
const { native } = emoji;
|
const { emoji } = e;
|
||||||
Transforms.insertText(editor, native);
|
Transforms.insertText(editor, emoji);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -153,6 +154,7 @@ export default function ChatTextField(props: Props) {
|
|||||||
renderElement={p => <Element {...p} />}
|
renderElement={p => <Element {...p} />}
|
||||||
placeholder="Chat message goes here..."
|
placeholder="Chat message goes here..."
|
||||||
style={{ width: '100%' }}
|
style={{ width: '100%' }}
|
||||||
|
autoFocus
|
||||||
/>
|
/>
|
||||||
</Slate>
|
</Slate>
|
||||||
<button
|
<button
|
||||||
@ -174,7 +176,7 @@ export default function ChatTextField(props: Props) {
|
|||||||
trigger="click"
|
trigger="click"
|
||||||
onVisibleChange={visible => setShowEmojis(visible)}
|
onVisibleChange={visible => setShowEmojis(visible)}
|
||||||
visible={showEmojis}
|
visible={showEmojis}
|
||||||
placement="bottomLeft"
|
// placement="topRight"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
// import data from '@emoji-mart/data';
|
import React, { useEffect, useRef, useState } from 'react';
|
||||||
import React, { useRef } from 'react';
|
import { createPicker } from 'picmo';
|
||||||
|
|
||||||
|
const CUSTOM_EMOJI_URL = '/api/emoji';
|
||||||
interface Props {
|
interface Props {
|
||||||
// eslint-disable-next-line react/no-unused-prop-types
|
// eslint-disable-next-line react/no-unused-prop-types
|
||||||
onEmojiSelect: (emoji: string) => void;
|
onEmojiSelect: (emoji: string) => void;
|
||||||
@ -8,28 +9,33 @@ interface Props {
|
|||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||||
export default function EmojiPicker(props: Props) {
|
export default function EmojiPicker(props: Props) {
|
||||||
|
const [customEmoji, setCustomEmoji] = useState([]);
|
||||||
|
const { onEmojiSelect } = props;
|
||||||
const ref = useRef();
|
const ref = useRef();
|
||||||
|
|
||||||
// TODO: Pull this custom emoji data in from the emoji API.
|
const getCustomEmoji = async () => {
|
||||||
// const custom = [
|
try {
|
||||||
// {
|
const response = await fetch(CUSTOM_EMOJI_URL);
|
||||||
// emojis: [
|
const emoji = await response.json();
|
||||||
// {
|
setCustomEmoji(emoji);
|
||||||
// id: 'party_parrot',
|
} catch (e) {
|
||||||
// name: 'Party Parrot',
|
console.error('cannot fetch custom emoji', e);
|
||||||
// keywords: ['dance', 'dancing'],
|
}
|
||||||
// skins: [{ src: 'https://watch.owncast.online/img/emoji/bluntparrot.gif' }],
|
};
|
||||||
// },
|
|
||||||
// ],
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// TODO: Fix the emoji picker from throwing errors.
|
// Fetch the custom emoji on component mount.
|
||||||
// useEffect(() => {
|
useEffect(() => {
|
||||||
// import('emoji-mart').then(EmojiMart => {
|
getCustomEmoji();
|
||||||
// new EmojiMart.Picker({ ...props, data, ref });
|
}, []);
|
||||||
// });
|
|
||||||
// }, []);
|
// Recreate the emoji picker when the custom emoji changes.
|
||||||
|
useEffect(() => {
|
||||||
|
const picker = createPicker({ rootElement: ref.current, custom: customEmoji });
|
||||||
|
picker.addEventListener('emoji:select', event => {
|
||||||
|
console.log('Emoji selected:', event.emoji);
|
||||||
|
onEmojiSelect(event);
|
||||||
|
});
|
||||||
|
}, [customEmoji]);
|
||||||
|
|
||||||
return <div ref={ref} />;
|
return <div ref={ref} />;
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,7 @@ module.exports = withLess({
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: '/img/:path*',
|
source: '/img/:path*',
|
||||||
destination: 'http://localhost:8080/hls/:path*', // Proxy to Backend to work around CORS.
|
destination: 'http://localhost:8080/img/:path*', // Proxy to Backend to work around CORS.
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
source: '/logo',
|
source: '/logo',
|
||||||
|
45
web/package-lock.json
generated
45
web/package-lock.json
generated
@ -18,11 +18,11 @@
|
|||||||
"chartkick": "4.1.1",
|
"chartkick": "4.1.1",
|
||||||
"classnames": "2.3.1",
|
"classnames": "2.3.1",
|
||||||
"date-fns": "2.28.0",
|
"date-fns": "2.28.0",
|
||||||
"emoji-mart": "^5.0.0",
|
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"markdown-it": "12.3.2",
|
"markdown-it": "12.3.2",
|
||||||
"next": "^12.1.5",
|
"next": "^12.1.5",
|
||||||
"next-with-less": "^2.0.5",
|
"next-with-less": "^2.0.5",
|
||||||
|
"picmo": "^5.1.0",
|
||||||
"postcss-flexbugs-fixes": "^5.0.2",
|
"postcss-flexbugs-fixes": "^5.0.2",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
"rc-overflow": "1.2.4",
|
"rc-overflow": "1.2.4",
|
||||||
@ -16298,17 +16298,21 @@
|
|||||||
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
|
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/emoji-mart": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-4O75LxV/RPOrtC9+0qhHhfPgJgW/Kwc4zv15h190liC3vJ/5RVibIrnPlDZ0xqYx0bPVOy3W/QcDTZY+jq1qOw=="
|
|
||||||
},
|
|
||||||
"node_modules/emoji-regex": {
|
"node_modules/emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/emojibase": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ==",
|
||||||
|
"funding": {
|
||||||
|
"type": "ko-fi",
|
||||||
|
"url": "https://ko-fi.com/milesjohnson"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/emojis-list": {
|
"node_modules/emojis-list": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||||
@ -25569,6 +25573,17 @@
|
|||||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"node_modules/picmo": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/picmo/-/picmo-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-gbq6gih+GMC3A+IAZloz/0imSCyTB1Ea8BNDLOTKvThg++a4h1KIspTXQO2S/DHDoB1arDTzE6BLcUjuQxkiMw==",
|
||||||
|
"dependencies": {
|
||||||
|
"emojibase": "^6.1.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sponsors/joeattardi"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picocolors": {
|
"node_modules/picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
@ -44952,17 +44967,17 @@
|
|||||||
"dev": true,
|
"dev": true,
|
||||||
"peer": true
|
"peer": true
|
||||||
},
|
},
|
||||||
"emoji-mart": {
|
|
||||||
"version": "5.0.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/emoji-mart/-/emoji-mart-5.0.0.tgz",
|
|
||||||
"integrity": "sha512-4O75LxV/RPOrtC9+0qhHhfPgJgW/Kwc4zv15h190liC3vJ/5RVibIrnPlDZ0xqYx0bPVOy3W/QcDTZY+jq1qOw=="
|
|
||||||
},
|
|
||||||
"emoji-regex": {
|
"emoji-regex": {
|
||||||
"version": "9.2.2",
|
"version": "9.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"emojibase": {
|
||||||
|
"version": "6.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/emojibase/-/emojibase-6.1.0.tgz",
|
||||||
|
"integrity": "sha512-1GkKJPXP6tVkYJHOBSJHoGOr/6uaDxZ9xJ6H7m6PfdGXTmQgbALHLWaVRY4Gi/qf5x/gT/NUXLPuSHYLqtLtrQ=="
|
||||||
|
},
|
||||||
"emojis-list": {
|
"emojis-list": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
|
||||||
@ -52101,6 +52116,14 @@
|
|||||||
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
"integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"picmo": {
|
||||||
|
"version": "5.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/picmo/-/picmo-5.1.0.tgz",
|
||||||
|
"integrity": "sha512-gbq6gih+GMC3A+IAZloz/0imSCyTB1Ea8BNDLOTKvThg++a4h1KIspTXQO2S/DHDoB1arDTzE6BLcUjuQxkiMw==",
|
||||||
|
"requires": {
|
||||||
|
"emojibase": "^6.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"picocolors": {
|
"picocolors": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz",
|
||||||
|
@ -22,11 +22,11 @@
|
|||||||
"chartkick": "4.1.1",
|
"chartkick": "4.1.1",
|
||||||
"classnames": "2.3.1",
|
"classnames": "2.3.1",
|
||||||
"date-fns": "2.28.0",
|
"date-fns": "2.28.0",
|
||||||
"emoji-mart": "^5.0.0",
|
|
||||||
"lodash": "4.17.21",
|
"lodash": "4.17.21",
|
||||||
"markdown-it": "12.3.2",
|
"markdown-it": "12.3.2",
|
||||||
"next": "^12.1.5",
|
"next": "^12.1.5",
|
||||||
"next-with-less": "^2.0.5",
|
"next-with-less": "^2.0.5",
|
||||||
|
"picmo": "^5.1.0",
|
||||||
"postcss-flexbugs-fixes": "^5.0.2",
|
"postcss-flexbugs-fixes": "^5.0.2",
|
||||||
"prop-types": "15.8.1",
|
"prop-types": "15.8.1",
|
||||||
"rc-overflow": "1.2.4",
|
"rc-overflow": "1.2.4",
|
||||||
|
Loading…
x
Reference in New Issue
Block a user