Smilies bei Nachrichten
This commit is contained in:
@@ -10,6 +10,68 @@ import {
|
||||
decryptMsg,
|
||||
} from '../crypto.js';
|
||||
|
||||
// ── Emoji-Konvertierung ───────────────────────────────────────────────────────
|
||||
const EMOJI_MAP = {
|
||||
':D':'😁', ':)':'🙂', ':-)':'🙂', '(:':'🙂', ';)':'😉', ';-)':'😉',
|
||||
':P':'😛', ':-P':'😛', ':p':'😛', ':O':'😮', ':-O':'😮', ':o':'😮',
|
||||
':(':'😢', ':-(':'😢', ":'(":'😭', '>:(':"😠", '>:-(':"😠",
|
||||
':*':'😘', ':-*':'😘', '<3':'❤️', '</3':'💔',
|
||||
'xD':'😆', 'XD':'😆', 'x)':"😄",
|
||||
':/':"😕", ':-/':"😕", ':|':"😐", ':-|':"😐",
|
||||
'B)':"😎", 'B-)':"😎", '^_^':"😊", '-_-':"😑",
|
||||
'O:)':"😇", 'O:-)':"😇", '>:)':"😈",
|
||||
':3':"🐱", ':$':"😳",
|
||||
};
|
||||
|
||||
// Ersetze Kürzel am Ende des Textes (nach Leerzeichen oder Satzanfang)
|
||||
function convertEmojis(text) {
|
||||
let result = text;
|
||||
for (const [code, emoji] of Object.entries(EMOJI_MAP)) {
|
||||
const escaped = code.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
||||
result = result.replace(new RegExp(`(^|\\s)${escaped}(?=\\s|$)`, 'g'), `$1${emoji}`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// ── Emoji-Picker Daten ────────────────────────────────────────────────────────
|
||||
const EMOJI_GROUPS = [
|
||||
{ label:'Smileys', emojis:['😀','😁','😂','🤣','😊','😇','🙂','😉','😌','😍','🥰','😘','😎','🤩','😏','😒','😞','😢','😭','😤','😠','😡','🤬','😈','👿','💀','😱','😨','😰','😓','🤔','🤐','😶','😐','😑','😬','🙄','😴','🤧','🤒','😷','🤕'] },
|
||||
{ label:'Gesten', emojis:['👍','👎','👌','✌️','🤞','🤟','🤙','👋','🤚','🖐','✋','🤜','🤛','👏','🙌','🤝','🙏','💪','🫶','❤️','🧡','💛','💚','💙','💜','🖤','💔','💯','💥','✨','🎉','🔥','⭐','🌟'] },
|
||||
{ label:'Dinge', emojis:['😂💀','🎮','🏆','🎯','🎲','🃏','🎸','🎵','🎤','📱','💻','⌨️','🖱️','📷','🎬','📺','🚀','🛸','🌍','🌈','☀️','🌙','⭐','🍕','🍔','🍟','🌮','🍩','🍺','☕','🧃'] },
|
||||
];
|
||||
|
||||
function EmojiPicker({ onSelect, onClose }) {
|
||||
const [group, setGroup] = useState(0);
|
||||
return (
|
||||
<div style={{ position:'absolute', bottom:'100%', right:0, marginBottom:6, zIndex:100,
|
||||
background:'#1a1a1e', border:'1px solid rgba(255,255,255,0.12)', borderRadius:12,
|
||||
width:272, boxShadow:'0 8px 32px rgba(0,0,0,0.5)' }}
|
||||
onMouseDown={e => e.preventDefault()}>
|
||||
<div style={{ display:'flex', borderBottom:'1px solid rgba(255,255,255,0.07)', padding:'6px 8px', gap:4 }}>
|
||||
{EMOJI_GROUPS.map((g,i) => (
|
||||
<button key={i} onClick={() => setGroup(i)} style={{ flex:1, background: group===i ?
|
||||
'rgba(78,205,196,0.15)' : 'transparent', border:'none', borderRadius:7,
|
||||
color: group===i ? '#4ecdc4' : 'rgba(255,255,255,0.4)', cursor:'pointer',
|
||||
fontSize:9, fontFamily:'monospace', padding:'4px 2px' }}>{g.label}</button>
|
||||
))}
|
||||
</div>
|
||||
<div style={{ display:'flex', flexWrap:'wrap', padding:8, gap:2, maxHeight:180, overflowY:'auto' }}>
|
||||
{EMOJI_GROUPS[group].emojis.filter(e => e.length <= 2 || [...e].length <= 2).concat(
|
||||
EMOJI_GROUPS[group].emojis.filter(e => [...e].length > 2)
|
||||
).map((em,i) => (
|
||||
<button key={i} onClick={() => onSelect(em)} style={{ background:'transparent', border:'none',
|
||||
borderRadius:6, cursor:'pointer', fontSize:20, padding:'4px 5px',
|
||||
transition:'background 0.1s' }}
|
||||
onMouseEnter={e => e.target.style.background='rgba(255,255,255,0.08)'}
|
||||
onMouseLeave={e => e.target.style.background='transparent'}>
|
||||
{em}
|
||||
</button>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function Nachrichten({ toast, mobile }) {
|
||||
const [kp, setKp] = useState(null);
|
||||
const [initError, setInitError] = useState(false);
|
||||
@@ -21,6 +83,7 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
const [partnerFp, setPartnerFp] = useState('');
|
||||
const [text, setText] = useState('');
|
||||
const [sending, setSending] = useState(false);
|
||||
const [showPicker, setShowPicker] = useState(false);
|
||||
const bottomRef = useRef(null);
|
||||
const pollRef = useRef(null);
|
||||
|
||||
@@ -367,19 +430,42 @@ export default function Nachrichten({ toast, mobile }) {
|
||||
Senden nicht möglich
|
||||
</div>
|
||||
) : (
|
||||
<div style={{ display:'flex', gap:8, alignItems:'flex-end' }}>
|
||||
<div style={{ display:'flex', gap:8, alignItems:'flex-end', position:'relative' }}>
|
||||
{showPicker && (
|
||||
<EmojiPicker
|
||||
onSelect={em => { setText(t => t + em); setShowPicker(false); }}
|
||||
onClose={() => setShowPicker(false)}
|
||||
/>
|
||||
)}
|
||||
<textarea
|
||||
value={text} onChange={e => setText(e.target.value)}
|
||||
value={text}
|
||||
onChange={e => {
|
||||
const val = e.target.value;
|
||||
// Kürzel nur konvertieren wenn gerade ein Leerzeichen oder Enter getippt wurde
|
||||
const last = val[val.length - 1];
|
||||
if (last === ' ' || last === '\n') {
|
||||
setText(convertEmojis(val));
|
||||
} else {
|
||||
setText(val);
|
||||
}
|
||||
}}
|
||||
onKeyDown={e => { if (e.key==='Enter' && !e.shiftKey) { e.preventDefault(); send(); }}}
|
||||
placeholder="Nachricht… (Enter senden · Shift+Enter neue Zeile)"
|
||||
rows={2}
|
||||
style={{ ...S.inp, resize:'none', flex:1, fontSize:13, padding:'8px 10px',
|
||||
lineHeight:1.45, minHeight:42 }}
|
||||
/>
|
||||
<button onClick={send} disabled={sending || !text.trim()} style={{
|
||||
...S.btn('#4ecdc4'), padding:'10px 16px', flexShrink:0, alignSelf:'stretch',
|
||||
opacity: sending || !text.trim() ? 0.3 : 1, fontSize:17, lineHeight:1,
|
||||
}}>↑</button>
|
||||
<div style={{ display:'flex', flexDirection:'column', gap:4, flexShrink:0, alignSelf:'stretch' }}>
|
||||
<button onClick={() => setShowPicker(v => !v)} style={{
|
||||
background: showPicker ? 'rgba(78,205,196,0.12)' : 'rgba(255,255,255,0.05)',
|
||||
border:`1px solid ${showPicker ? 'rgba(78,205,196,0.3)' : 'rgba(255,255,255,0.1)'}`,
|
||||
borderRadius:8, cursor:'pointer', fontSize:17, lineHeight:1,
|
||||
padding:'5px 8px', flexShrink:0 }}>😊</button>
|
||||
<button onClick={send} disabled={sending || !text.trim()} style={{
|
||||
...S.btn('#4ecdc4'), flex:1, padding:'0 14px',
|
||||
opacity: sending || !text.trim() ? 0.3 : 1, fontSize:17, lineHeight:1,
|
||||
}}>↑</button>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user