close #2 : added autocomplete for display name & replace fusejs
This commit is contained in:
parent
c81628a66e
commit
eb667bc436
6 changed files with 183 additions and 151 deletions
|
@ -2,7 +2,6 @@
|
||||||
import React, { useState, useEffect } from 'react';
|
import React, { useState, useEffect } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import './ChannelViewCmdBar.scss';
|
import './ChannelViewCmdBar.scss';
|
||||||
import Fuse from 'fuse.js';
|
|
||||||
import parse from 'html-react-parser';
|
import parse from 'html-react-parser';
|
||||||
import twemoji from 'twemoji';
|
import twemoji from 'twemoji';
|
||||||
|
|
||||||
|
@ -17,7 +16,8 @@ import {
|
||||||
openInviteUser,
|
openInviteUser,
|
||||||
openReadReceipts,
|
openReadReceipts,
|
||||||
} from '../../../client/action/navigation';
|
} from '../../../client/action/navigation';
|
||||||
import { searchEmoji } from '../emoji-board/emoji';
|
import { emojis } from '../emoji-board/emoji';
|
||||||
|
import AsyncSearch from '../../../util/AsyncSearch';
|
||||||
|
|
||||||
import Text from '../../atoms/text/Text';
|
import Text from '../../atoms/text/Text';
|
||||||
import Button from '../../atoms/button/Button';
|
import Button from '../../atoms/button/Button';
|
||||||
|
@ -74,6 +74,7 @@ function CmdHelp() {
|
||||||
<Text variant="b2">{'>@people_name'}</Text>
|
<Text variant="b2">{'>@people_name'}</Text>
|
||||||
<MenuHeader>Autofill command</MenuHeader>
|
<MenuHeader>Autofill command</MenuHeader>
|
||||||
<Text variant="b2">:emoji_name:</Text>
|
<Text variant="b2">:emoji_name:</Text>
|
||||||
|
<Text variant="b2">@name</Text>
|
||||||
</>
|
</>
|
||||||
)}
|
)}
|
||||||
render={(toggleMenu) => (
|
render={(toggleMenu) => (
|
||||||
|
@ -176,6 +177,7 @@ function getCmdActivationMessage(prefix) {
|
||||||
'>#': () => genMessage('Go-to command mode activated. ', 'Type channel name for suggestions.'),
|
'>#': () => genMessage('Go-to command mode activated. ', 'Type channel name for suggestions.'),
|
||||||
'>@': () => genMessage('Go-to command mode activated. ', 'Type people name for suggestions.'),
|
'>@': () => genMessage('Go-to command mode activated. ', 'Type people name for suggestions.'),
|
||||||
':': () => genMessage('Emoji autofill command mode activated. ', 'Type emoji shortcut for suggestions.'),
|
':': () => genMessage('Emoji autofill command mode activated. ', 'Type emoji shortcut for suggestions.'),
|
||||||
|
'@': () => genMessage('Name autofill command mode activated. ', 'Type name for suggestions.'),
|
||||||
};
|
};
|
||||||
return cmd[prefix]?.();
|
return cmd[prefix]?.();
|
||||||
}
|
}
|
||||||
|
@ -192,163 +194,166 @@ CmdItem.propTypes = {
|
||||||
children: PropTypes.node.isRequired,
|
children: PropTypes.node.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
function searchInRoomIds(roomIds, term) {
|
function getCmdSuggestions({ prefix, option, suggestions }, fireCmd) {
|
||||||
const rooms = roomIds.map((rId) => {
|
function getGenCmdSuggestions(cmdPrefix, cmds) {
|
||||||
const room = initMatrix.matrixClient.getRoom(rId);
|
const cmdOptString = (typeof option === 'string') ? `/${option}` : '/?';
|
||||||
return {
|
return cmds.map((cmd) => (
|
||||||
name: room.name,
|
|
||||||
roomId: room.roomId,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
const fuse = new Fuse(rooms, {
|
|
||||||
includeScore: true,
|
|
||||||
keys: ['name'],
|
|
||||||
threshold: '0.3',
|
|
||||||
});
|
|
||||||
return fuse.search(term);
|
|
||||||
}
|
|
||||||
|
|
||||||
function searchCommands(term) {
|
|
||||||
const fuse = new Fuse(commands, {
|
|
||||||
includeScore: true,
|
|
||||||
keys: ['name'],
|
|
||||||
threshold: '0.3',
|
|
||||||
});
|
|
||||||
return fuse.search(term);
|
|
||||||
}
|
|
||||||
|
|
||||||
let perfectMatchCmd = null;
|
|
||||||
function getCmdSuggestions({ prefix, slug }, fireCmd, viewEvent) {
|
|
||||||
function getRoomsSuggestion(cmdPrefix, rooms, roomSlug) {
|
|
||||||
const result = searchInRoomIds(rooms, roomSlug);
|
|
||||||
if (result.length === 0) viewEvent.emit('cmd_error');
|
|
||||||
perfectMatchCmd = {
|
|
||||||
prefix: cmdPrefix,
|
|
||||||
slug: roomSlug,
|
|
||||||
result: result[0]?.item || null,
|
|
||||||
};
|
|
||||||
return result.map((finding) => (
|
|
||||||
<CmdItem
|
<CmdItem
|
||||||
key={finding.item.roomId}
|
key={cmd.name}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
fireCmd({
|
fireCmd({
|
||||||
prefix: cmdPrefix,
|
prefix: cmdPrefix,
|
||||||
slug: roomSlug,
|
option,
|
||||||
result: finding.item,
|
result: cmd,
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<Text variant="b2">{finding.item.name}</Text>
|
<Text variant="b2">{`${cmd.name}${cmd.isOptions ? cmdOptString : ''}`}</Text>
|
||||||
</CmdItem>
|
</CmdItem>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGenCmdSuggestions(cmdPrefix, cmdSlug) {
|
function getRoomsSuggestion(cmdPrefix, rooms) {
|
||||||
const cmdSlugParts = cmdSlug.split('/');
|
return rooms.map((room) => (
|
||||||
const cmdSlugOption = cmdSlugParts[1];
|
<CmdItem
|
||||||
const result = searchCommands(cmdSlugParts[0]);
|
key={room.roomId}
|
||||||
if (result.length === 0) viewEvent.emit('cmd_error');
|
onClick={() => {
|
||||||
perfectMatchCmd = {
|
fireCmd({
|
||||||
prefix: cmdPrefix,
|
prefix: cmdPrefix,
|
||||||
slug: cmdSlug,
|
result: room,
|
||||||
option: cmdSlugOption,
|
});
|
||||||
result: result[0]?.item || null,
|
}}
|
||||||
};
|
>
|
||||||
return result.map((finding) => {
|
<Text variant="b2">{room.name}</Text>
|
||||||
let option = '';
|
</CmdItem>
|
||||||
if (finding.item.isOptions) {
|
));
|
||||||
if (typeof cmdSlugOption === 'string') option = `/${cmdSlugOption}`;
|
|
||||||
else option = '/?';
|
|
||||||
}
|
|
||||||
return (
|
|
||||||
<CmdItem
|
|
||||||
key={finding.item.name}
|
|
||||||
onClick={() => {
|
|
||||||
fireCmd({
|
|
||||||
prefix: cmdPrefix,
|
|
||||||
slug: cmdSlug,
|
|
||||||
option: cmdSlugOption,
|
|
||||||
result: finding.item,
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
>
|
|
||||||
<Text variant="b2">{`${finding.item.name}${option}`}</Text>
|
|
||||||
</CmdItem>
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getEmojiSuggestion(emPrefix, shortcutSlug) {
|
function getEmojiSuggestion(emPrefix, emos) {
|
||||||
let searchTerm = shortcutSlug;
|
return emos.map((emoji) => (
|
||||||
if (searchTerm.length <= 3) {
|
|
||||||
if (searchTerm.match(/^[-]?(\))/)) searchTerm = 'smile';
|
|
||||||
else if (searchTerm.match(/^[-]?(s|S)/)) searchTerm = 'confused';
|
|
||||||
else if (searchTerm.match(/^[-]?(o|O|0)/)) searchTerm = 'astonished';
|
|
||||||
else if (searchTerm.match(/^[-]?(\|)/)) searchTerm = 'neutral_face';
|
|
||||||
else if (searchTerm.match(/^[-]?(d|D)/)) searchTerm = 'grin';
|
|
||||||
else if (searchTerm.match(/^[-]?(\/)/)) searchTerm = 'frown';
|
|
||||||
else if (searchTerm.match(/^[-]?(p|P)/)) searchTerm = 'stick_out_tongue';
|
|
||||||
else if (searchTerm.match(/^'[-]?(\()/)) searchTerm = 'cry';
|
|
||||||
else if (searchTerm.match(/^[-]?(x|X)/)) searchTerm = 'dizzy_face';
|
|
||||||
else if (searchTerm.match(/^[-]?(\()/)) searchTerm = 'pleading_face';
|
|
||||||
else if (searchTerm.match(/^[-]?(\$)/)) searchTerm = 'money';
|
|
||||||
else if (searchTerm.match(/^(<3)/)) searchTerm = 'heart';
|
|
||||||
}
|
|
||||||
const result = searchEmoji(searchTerm);
|
|
||||||
if (result.length === 0) viewEvent.emit('cmd_error');
|
|
||||||
perfectMatchCmd = {
|
|
||||||
prefix: emPrefix,
|
|
||||||
slug: shortcutSlug,
|
|
||||||
result: result[0]?.item || null,
|
|
||||||
};
|
|
||||||
return result.map((finding) => (
|
|
||||||
<CmdItem
|
<CmdItem
|
||||||
key={finding.item.hexcode}
|
key={emoji.hexcode}
|
||||||
onClick={() => fireCmd({
|
onClick={() => fireCmd({
|
||||||
prefix: emPrefix,
|
prefix: emPrefix,
|
||||||
slug: shortcutSlug,
|
result: emoji,
|
||||||
result: finding.item,
|
|
||||||
})}
|
})}
|
||||||
>
|
>
|
||||||
{
|
{
|
||||||
parse(twemoji.parse(
|
parse(twemoji.parse(
|
||||||
finding.item.unicode,
|
emoji.unicode,
|
||||||
{
|
{
|
||||||
attributes: () => ({
|
attributes: () => ({
|
||||||
unicode: finding.item.unicode,
|
unicode: emoji.unicode,
|
||||||
shortcodes: finding.item.shortcodes?.toString(),
|
shortcodes: emoji.shortcodes?.toString(),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
<Text variant="b2">{`:${emoji.shortcode}:`}</Text>
|
||||||
|
</CmdItem>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
function getNameSuggestion(namePrefix, members) {
|
||||||
|
return members.map((member) => (
|
||||||
|
<CmdItem
|
||||||
|
key={member.userId}
|
||||||
|
onClick={() => {
|
||||||
|
fireCmd({
|
||||||
|
prefix: namePrefix,
|
||||||
|
result: member,
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Text variant="b2">{member.name}</Text>
|
||||||
</CmdItem>
|
</CmdItem>
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
const { roomList } = initMatrix;
|
|
||||||
const cmd = {
|
const cmd = {
|
||||||
'/': (command) => getGenCmdSuggestions(prefix, command),
|
'/': (cmds) => getGenCmdSuggestions(prefix, cmds),
|
||||||
'>*': (space) => getRoomsSuggestion(prefix, [...roomList.spaces], space),
|
'>*': (spaces) => getRoomsSuggestion(prefix, spaces),
|
||||||
'>#': (channel) => getRoomsSuggestion(prefix, [...roomList.rooms], channel),
|
'>#': (channels) => getRoomsSuggestion(prefix, channels),
|
||||||
'>@': (people) => getRoomsSuggestion(prefix, [...roomList.directs], people),
|
'>@': (peoples) => getRoomsSuggestion(prefix, peoples),
|
||||||
':': (emojiShortcut) => getEmojiSuggestion(prefix, emojiShortcut),
|
':': (emos) => getEmojiSuggestion(prefix, emos),
|
||||||
|
'@': (members) => getNameSuggestion(prefix, members),
|
||||||
};
|
};
|
||||||
return cmd[prefix]?.(slug);
|
return cmd[prefix]?.(suggestions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const asyncSearch = new AsyncSearch();
|
||||||
|
let cmdPrefix;
|
||||||
|
let cmdOption;
|
||||||
function ChannelViewCmdBar({ roomId, roomTimeline, viewEvent }) {
|
function ChannelViewCmdBar({ roomId, roomTimeline, viewEvent }) {
|
||||||
const [cmd, setCmd] = useState(null);
|
const [cmd, setCmd] = useState(null);
|
||||||
|
|
||||||
|
function displaySuggestions(suggestions) {
|
||||||
|
if (suggestions.length === 0) {
|
||||||
|
setCmd({ prefix: cmd?.prefix || cmdPrefix, error: 'No suggestion found.' });
|
||||||
|
viewEvent.emit('cmd_error');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setCmd({ prefix: cmd?.prefix || cmdPrefix, suggestions, option: cmdOption });
|
||||||
|
}
|
||||||
|
|
||||||
function processCmd(prefix, slug) {
|
function processCmd(prefix, slug) {
|
||||||
setCmd({ prefix, slug });
|
let searchTerm = slug;
|
||||||
|
cmdOption = undefined;
|
||||||
|
cmdPrefix = prefix;
|
||||||
|
if (prefix === '/') {
|
||||||
|
const cmdSlugParts = slug.split('/');
|
||||||
|
[searchTerm, cmdOption] = cmdSlugParts;
|
||||||
|
}
|
||||||
|
if (prefix === ':') {
|
||||||
|
if (searchTerm.length <= 3) {
|
||||||
|
if (searchTerm.match(/^[-]?(\))$/)) searchTerm = 'smile';
|
||||||
|
else if (searchTerm.match(/^[-]?(s|S)$/)) searchTerm = 'confused';
|
||||||
|
else if (searchTerm.match(/^[-]?(o|O|0)$/)) searchTerm = 'astonished';
|
||||||
|
else if (searchTerm.match(/^[-]?(\|)$/)) searchTerm = 'neutral_face';
|
||||||
|
else if (searchTerm.match(/^[-]?(d|D)$/)) searchTerm = 'grin';
|
||||||
|
else if (searchTerm.match(/^[-]?(\/)$/)) searchTerm = 'frown';
|
||||||
|
else if (searchTerm.match(/^[-]?(p|P)$/)) searchTerm = 'stick_out_tongue';
|
||||||
|
else if (searchTerm.match(/^'[-]?(\()$/)) searchTerm = 'cry';
|
||||||
|
else if (searchTerm.match(/^[-]?(x|X)$/)) searchTerm = 'dizzy_face';
|
||||||
|
else if (searchTerm.match(/^[-]?(\()$/)) searchTerm = 'pleading_face';
|
||||||
|
else if (searchTerm.match(/^[-]?(\$)$/)) searchTerm = 'money';
|
||||||
|
else if (searchTerm.match(/^(<3)$/)) searchTerm = 'heart';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
asyncSearch.search(searchTerm);
|
||||||
}
|
}
|
||||||
function activateCmd(prefix) {
|
function activateCmd(prefix) {
|
||||||
setCmd({ prefix });
|
setCmd({ prefix });
|
||||||
perfectMatchCmd = null;
|
cmdPrefix = prefix;
|
||||||
|
|
||||||
|
const { roomList, matrixClient } = initMatrix;
|
||||||
|
function getRooms(roomIds) {
|
||||||
|
return roomIds.map((rId) => {
|
||||||
|
const room = matrixClient.getRoom(rId);
|
||||||
|
return {
|
||||||
|
name: room.name,
|
||||||
|
roomId: room.roomId,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
}
|
||||||
|
const setupSearch = {
|
||||||
|
'/': () => asyncSearch.setup(commands, { keys: ['name'], isContain: true }),
|
||||||
|
'>*': () => asyncSearch.setup(getRooms([...roomList.spaces]), { keys: ['name'], limit: 20 }),
|
||||||
|
'>#': () => asyncSearch.setup(getRooms([...roomList.rooms]), { keys: ['name'], limit: 20 }),
|
||||||
|
'>@': () => asyncSearch.setup(getRooms([...roomList.directs]), { keys: ['name'], limit: 20 }),
|
||||||
|
':': () => asyncSearch.setup(emojis, { keys: ['shortcode'], limit: 20 }),
|
||||||
|
'@': () => asyncSearch.setup(matrixClient.getRoom(roomId).getJoinedMembers().map((member) => ({
|
||||||
|
name: member.name,
|
||||||
|
userId: member.userId.slice(1),
|
||||||
|
})), { keys: ['name', 'userId'], limit: 20 }),
|
||||||
|
};
|
||||||
|
setupSearch[prefix]?.();
|
||||||
}
|
}
|
||||||
function deactivateCmd() {
|
function deactivateCmd() {
|
||||||
setCmd(null);
|
setCmd(null);
|
||||||
perfectMatchCmd = null;
|
cmdOption = undefined;
|
||||||
|
cmdPrefix = undefined;
|
||||||
}
|
}
|
||||||
function fireCmd(myCmd) {
|
function fireCmd(myCmd) {
|
||||||
if (myCmd.prefix.match(/^>[*#@]$/)) {
|
if (myCmd.prefix.match(/^>[*#@]$/)) {
|
||||||
|
@ -364,34 +369,44 @@ function ChannelViewCmdBar({ roomId, roomTimeline, viewEvent }) {
|
||||||
replace: myCmd.result.unicode,
|
replace: myCmd.result.unicode,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (myCmd.prefix === '@') {
|
||||||
|
viewEvent.emit('cmd_fired', {
|
||||||
|
replace: myCmd.result.name,
|
||||||
|
});
|
||||||
|
}
|
||||||
deactivateCmd();
|
deactivateCmd();
|
||||||
}
|
}
|
||||||
function executeCmd() {
|
function executeCmd() {
|
||||||
if (perfectMatchCmd === null) return;
|
if (cmd.suggestions.length === 0) return;
|
||||||
if (perfectMatchCmd.result === null) return;
|
fireCmd({
|
||||||
fireCmd(perfectMatchCmd);
|
prefix: cmd.prefix,
|
||||||
}
|
option: cmd.option,
|
||||||
function errorCmd() {
|
result: cmd.suggestions[0],
|
||||||
setCmd({ error: 'No suggestion found.' });
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
viewEvent.on('cmd_activate', activateCmd);
|
viewEvent.on('cmd_activate', activateCmd);
|
||||||
viewEvent.on('cmd_process', processCmd);
|
|
||||||
viewEvent.on('cmd_deactivate', deactivateCmd);
|
viewEvent.on('cmd_deactivate', deactivateCmd);
|
||||||
viewEvent.on('cmd_exe', executeCmd);
|
|
||||||
viewEvent.on('cmd_error', errorCmd);
|
|
||||||
return () => {
|
return () => {
|
||||||
deactivateCmd();
|
deactivateCmd();
|
||||||
viewEvent.removeListener('cmd_activate', activateCmd);
|
viewEvent.removeListener('cmd_activate', activateCmd);
|
||||||
viewEvent.removeListener('cmd_process', processCmd);
|
|
||||||
viewEvent.removeListener('cmd_deactivate', deactivateCmd);
|
viewEvent.removeListener('cmd_deactivate', deactivateCmd);
|
||||||
viewEvent.removeListener('cmd_exe', executeCmd);
|
|
||||||
viewEvent.removeListener('cmd_error', errorCmd);
|
|
||||||
};
|
};
|
||||||
}, [roomId]);
|
}, [roomId]);
|
||||||
|
|
||||||
if (cmd !== null && typeof cmd.error !== 'undefined') {
|
useEffect(() => {
|
||||||
|
viewEvent.on('cmd_process', processCmd);
|
||||||
|
viewEvent.on('cmd_exe', executeCmd);
|
||||||
|
asyncSearch.on(asyncSearch.RESULT_SENT, displaySuggestions);
|
||||||
|
return () => {
|
||||||
|
viewEvent.removeListener('cmd_process', processCmd);
|
||||||
|
viewEvent.removeListener('cmd_exe', executeCmd);
|
||||||
|
asyncSearch.removeListener(asyncSearch.RESULT_SENT, displaySuggestions);
|
||||||
|
};
|
||||||
|
}, [cmd]);
|
||||||
|
|
||||||
|
if (typeof cmd?.error === 'string') {
|
||||||
return (
|
return (
|
||||||
<div className="cmd-bar">
|
<div className="cmd-bar">
|
||||||
<div className="cmd-bar__info">
|
<div className="cmd-bar__info">
|
||||||
|
@ -408,8 +423,8 @@ function ChannelViewCmdBar({ roomId, roomTimeline, viewEvent }) {
|
||||||
<div className="cmd-bar">
|
<div className="cmd-bar">
|
||||||
<div className="cmd-bar__info">
|
<div className="cmd-bar__info">
|
||||||
{cmd === null && <CmdHelp />}
|
{cmd === null && <CmdHelp />}
|
||||||
{cmd !== null && typeof cmd.slug === 'undefined' && <div className="cmd-bar__info-indicator" /> }
|
{cmd !== null && typeof cmd.suggestions === 'undefined' && <div className="cmd-bar__info-indicator" /> }
|
||||||
{cmd !== null && typeof cmd.slug === 'string' && <Text variant="b3">TAB</Text>}
|
{cmd !== null && typeof cmd.suggestions !== 'undefined' && <Text variant="b3">TAB</Text>}
|
||||||
</div>
|
</div>
|
||||||
<div className="cmd-bar__content">
|
<div className="cmd-bar__content">
|
||||||
{cmd === null && (
|
{cmd === null && (
|
||||||
|
@ -419,10 +434,10 @@ function ChannelViewCmdBar({ roomId, roomTimeline, viewEvent }) {
|
||||||
viewEvent={viewEvent}
|
viewEvent={viewEvent}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{cmd !== null && typeof cmd.slug === 'undefined' && <Text className="cmd-bar__content-help" variant="b2">{getCmdActivationMessage(cmd.prefix)}</Text>}
|
{cmd !== null && typeof cmd.suggestions === 'undefined' && <Text className="cmd-bar__content-help" variant="b2">{getCmdActivationMessage(cmd.prefix)}</Text>}
|
||||||
{cmd !== null && typeof cmd.slug === 'string' && (
|
{cmd !== null && typeof cmd.suggestions !== 'undefined' && (
|
||||||
<ScrollView horizontal vertical={false} invisible>
|
<ScrollView horizontal vertical={false} invisible>
|
||||||
<div className="cmd-bar__content__suggestions">{getCmdSuggestions(cmd, fireCmd, viewEvent)}</div>
|
<div className="cmd-bar__content__suggestions">{getCmdSuggestions(cmd, fireCmd)}</div>
|
||||||
</ScrollView>
|
</ScrollView>
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -117,14 +117,10 @@
|
||||||
border-radius: var(--bo-radius) var(--bo-radius) 0 0;
|
border-radius: var(--bo-radius) var(--bo-radius) 0 0;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
|
|
||||||
[dir=rtl] & {
|
|
||||||
margin-right: 0;
|
|
||||||
margin-left: var(--sp-extra-tight);
|
|
||||||
}
|
|
||||||
|
|
||||||
& .emoji {
|
& .emoji {
|
||||||
width: 20px;
|
width: 20px;
|
||||||
height: 20px;
|
height: 20px;
|
||||||
|
margin-right: var(--sp-ultra-tight);
|
||||||
}
|
}
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
|
@ -136,4 +132,13 @@
|
||||||
border-bottom: 2px solid transparent;
|
border-bottom: 2px solid transparent;
|
||||||
outline: none;
|
outline: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[dir=rtl] & {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: var(--sp-extra-tight);
|
||||||
|
& .emoji {
|
||||||
|
margin-right: 0;
|
||||||
|
margin-left: var(--sp-ultra-tight);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
|
@ -29,7 +29,7 @@ import MarkdownIC from '../../../../public/res/ic/outlined/markdown.svg';
|
||||||
import FileIC from '../../../../public/res/ic/outlined/file.svg';
|
import FileIC from '../../../../public/res/ic/outlined/file.svg';
|
||||||
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
|
import CrossIC from '../../../../public/res/ic/outlined/cross.svg';
|
||||||
|
|
||||||
const CMD_REGEX = /(\/|>[#*@]|:)(\S*)$/;
|
const CMD_REGEX = /(\/|>[#*@]|:|@)(\S*)$/;
|
||||||
let isTyping = false;
|
let isTyping = false;
|
||||||
let isCmdActivated = false;
|
let isCmdActivated = false;
|
||||||
let cmdCursorPos = null;
|
let cmdCursorPos = null;
|
||||||
|
@ -90,20 +90,26 @@ function ChannelViewInput({
|
||||||
|
|
||||||
function activateCmd(prefix) {
|
function activateCmd(prefix) {
|
||||||
isCmdActivated = true;
|
isCmdActivated = true;
|
||||||
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-positive)';
|
requestAnimationFrame(() => {
|
||||||
|
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-positive)';
|
||||||
|
});
|
||||||
rightOptionsA11Y(false);
|
rightOptionsA11Y(false);
|
||||||
viewEvent.emit('cmd_activate', prefix);
|
viewEvent.emit('cmd_activate', prefix);
|
||||||
}
|
}
|
||||||
function deactivateCmd() {
|
function deactivateCmd() {
|
||||||
if (inputBaseRef.current !== null) {
|
if (inputBaseRef.current !== null) {
|
||||||
inputBaseRef.current.style.boxShadow = 'var(--bs-surface-border)';
|
requestAnimationFrame(() => {
|
||||||
|
inputBaseRef.current.style.boxShadow = 'var(--bs-surface-border)';
|
||||||
|
});
|
||||||
rightOptionsA11Y(true);
|
rightOptionsA11Y(true);
|
||||||
}
|
}
|
||||||
isCmdActivated = false;
|
isCmdActivated = false;
|
||||||
cmdCursorPos = null;
|
cmdCursorPos = null;
|
||||||
}
|
}
|
||||||
function errorCmd() {
|
function errorCmd() {
|
||||||
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-danger)';
|
requestAnimationFrame(() => {
|
||||||
|
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-danger)';
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function setCursorPosition(pos) {
|
function setCursorPosition(pos) {
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
|
@ -242,7 +248,9 @@ function ChannelViewInput({
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!isCmdActivated) activateCmd(cmdPrefix);
|
if (!isCmdActivated) activateCmd(cmdPrefix);
|
||||||
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-caution)';
|
requestAnimationFrame(() => {
|
||||||
|
inputBaseRef.current.style.boxShadow = '0 0 0 1px var(--bg-caution)';
|
||||||
|
});
|
||||||
viewEvent.emit('cmd_process', cmdPrefix, cmdSlug);
|
viewEvent.emit('cmd_process', cmdPrefix, cmdSlug);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,11 +53,15 @@ function addToGroup(emoji) {
|
||||||
|
|
||||||
const emojis = [];
|
const emojis = [];
|
||||||
emojisData.forEach((emoji) => {
|
emojisData.forEach((emoji) => {
|
||||||
const em = { ...emoji, shortcodes: shortcodes[emoji.hexcode] };
|
const myShortCodes = shortcodes[emoji.hexcode];
|
||||||
|
const em = {
|
||||||
|
...emoji,
|
||||||
|
shortcode: Array.isArray(myShortCodes) ? myShortCodes[0] : myShortCodes,
|
||||||
|
shortcodes: myShortCodes,
|
||||||
|
};
|
||||||
addToGroup(em);
|
addToGroup(em);
|
||||||
emojis.push(em);
|
emojis.push(em);
|
||||||
});
|
});
|
||||||
|
|
||||||
function searchEmoji(term) {
|
function searchEmoji(term) {
|
||||||
const options = {
|
const options = {
|
||||||
includeScore: true,
|
includeScore: true,
|
||||||
|
|
|
@ -7,7 +7,7 @@ class Navigation extends EventEmitter {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
this.activeTab = 'channels';
|
this.activeTab = 'channels';
|
||||||
this.selectedRoom = null;
|
this.activeRoomId = null;
|
||||||
this.isPeopleDrawerVisible = true;
|
this.isPeopleDrawerVisible = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -15,8 +15,8 @@ class Navigation extends EventEmitter {
|
||||||
return this.activeTab;
|
return this.activeTab;
|
||||||
}
|
}
|
||||||
|
|
||||||
getActiveRoom() {
|
getActiveRoomId() {
|
||||||
return this.selectedRoom;
|
return this.activeRoomId;
|
||||||
}
|
}
|
||||||
|
|
||||||
navigate(action) {
|
navigate(action) {
|
||||||
|
@ -26,8 +26,8 @@ class Navigation extends EventEmitter {
|
||||||
this.emit(cons.events.navigation.TAB_CHANGED, this.activeTab);
|
this.emit(cons.events.navigation.TAB_CHANGED, this.activeTab);
|
||||||
},
|
},
|
||||||
[cons.actions.navigation.SELECT_ROOM]: () => {
|
[cons.actions.navigation.SELECT_ROOM]: () => {
|
||||||
this.selectedRoom = action.roomId;
|
this.activeRoomId = action.roomId;
|
||||||
this.emit(cons.events.navigation.ROOM_SELECTED, this.selectedRoom);
|
this.emit(cons.events.navigation.ROOM_SELECTED, this.activeRoomId);
|
||||||
},
|
},
|
||||||
[cons.actions.navigation.TOGGLE_PEOPLE_DRAWER]: () => {
|
[cons.actions.navigation.TOGGLE_PEOPLE_DRAWER]: () => {
|
||||||
this.isPeopleDrawerVisible = !this.isPeopleDrawerVisible;
|
this.isPeopleDrawerVisible = !this.isPeopleDrawerVisible;
|
||||||
|
|
|
@ -82,7 +82,7 @@ class AsyncSearch extends EventEmitter {
|
||||||
if (lastFindingCount !== thisFindingCount) this._sendFindings();
|
if (lastFindingCount !== thisFindingCount) this._sendFindings();
|
||||||
|
|
||||||
this.searchUptoIndex = searchIndex + 1;
|
this.searchUptoIndex = searchIndex + 1;
|
||||||
queueMicrotask(() => this._find(thisSessionTimestamp, thisFindingCount));
|
setTimeout(() => this._find(thisSessionTimestamp, thisFindingCount));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue