Emojis, Markdown and better file uploading
This commit is contained in:
parent
7eba84b6ec
commit
82d18ac74d
|
@ -110,7 +110,7 @@
|
|||
</button>
|
||||
</div>
|
||||
<div class="message-input-wrapper">
|
||||
<input type="text" id="messageInput" placeholder="Send a message..." autofocus>
|
||||
<textarea style="font-family: sans-serif" id="messageInput" placeholder="Send a message..." autofocus></textarea>
|
||||
<button class="send-button" onclick="sendMessage()">
|
||||
<i class="fa-solid fa-paper-plane"></i>
|
||||
</button>
|
||||
|
|
|
@ -24,10 +24,17 @@ document.addEventListener('DOMContentLoaded', function() {
|
|||
chatHeader.insertBefore(menuToggle, chatHeader.firstChild);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('messageInput').addEventListener('input', function () {
|
||||
this.style.height = 'auto';
|
||||
this.style.height = (this.scrollHeight) + 'px';
|
||||
});
|
||||
|
||||
|
||||
// Add event listeners
|
||||
document.getElementById('messageInput').addEventListener('keypress', (event) => {
|
||||
if (event.key === 'Enter') {
|
||||
document.getElementById('messageInput').addEventListener('keydown', function(event) {
|
||||
if (event.key === 'Enter' && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
sendMessage();
|
||||
}
|
||||
});
|
||||
|
@ -264,6 +271,218 @@ function resetLoginButton() {
|
|||
}
|
||||
}
|
||||
|
||||
function markdownToHtmlDiv(markdown) {
|
||||
// Emoji mapping
|
||||
const emojiMap = {
|
||||
// 😀 Faces
|
||||
smile: '😄',
|
||||
happy: '😊',
|
||||
grin: '😁',
|
||||
laugh: '😂',
|
||||
joy: '🤣',
|
||||
wink: '😉',
|
||||
blush: '☺️',
|
||||
cool: '😎',
|
||||
smirk: '😏',
|
||||
thinking: '🤔',
|
||||
neutral: '😐',
|
||||
expressionless: '😑',
|
||||
sleepy: '😴',
|
||||
dizzy: '😵',
|
||||
surprised: '😲',
|
||||
scream: '😱',
|
||||
cry: '😢',
|
||||
sob: '😭',
|
||||
angry: '😠',
|
||||
rage: '😡',
|
||||
yum: '😋',
|
||||
relieved: '😌',
|
||||
confused: '😕',
|
||||
nerd: '🤓',
|
||||
zany: '🤪',
|
||||
shush: '🤫',
|
||||
hush: '🤐',
|
||||
|
||||
// ❤️ Emotions
|
||||
heart: '❤️',
|
||||
heartbroken: '💔',
|
||||
love: '😍',
|
||||
kiss: '😘',
|
||||
hug: '🤗',
|
||||
clap: '👏',
|
||||
pray: '🙏',
|
||||
ok: '👌',
|
||||
fingerscrossed: '🤞',
|
||||
thumbsup: '👍',
|
||||
thumbsdown: '👎',
|
||||
eyes: '👀',
|
||||
|
||||
// 🔥 Reactions
|
||||
fire: '🔥',
|
||||
100: '💯',
|
||||
poop: '💩',
|
||||
poo: '💩',
|
||||
skull: '💀',
|
||||
explosion: '💥',
|
||||
mindblown: '🤯',
|
||||
party: '🥳',
|
||||
tada: '🎉',
|
||||
balloon: '🎈',
|
||||
|
||||
// 🐶 Animals
|
||||
chicken: '🐔',
|
||||
dog: '🐶',
|
||||
cat: '🐱',
|
||||
fox: '🦊',
|
||||
panda: '🐼',
|
||||
pig: '🐷',
|
||||
cow: '🐮',
|
||||
rabbit: '🐰',
|
||||
bear: '🐻',
|
||||
unicorn: '🦄',
|
||||
monkey: '🐒',
|
||||
dragon: '🐉',
|
||||
snake: '🐍',
|
||||
|
||||
// 🍔 Food & Drink
|
||||
pizza: '🍕',
|
||||
burger: '🍔',
|
||||
fries: '🍟',
|
||||
hotdog: '🌭',
|
||||
taco: '🌮',
|
||||
ramen: '🍜',
|
||||
sushi: '🍣',
|
||||
icecream: '🍨',
|
||||
cake: '🎂',
|
||||
coffee: '☕',
|
||||
tea: '🍵',
|
||||
beer: '🍺',
|
||||
|
||||
// 🌍 Nature & Weather
|
||||
sun: '☀️',
|
||||
moon: '🌙',
|
||||
star: '⭐',
|
||||
cloud: '☁️',
|
||||
rain: '🌧️',
|
||||
snow: '❄️',
|
||||
lightning: '⚡',
|
||||
rainbow: '🌈',
|
||||
tree: '🌳',
|
||||
flower: '🌸',
|
||||
|
||||
// ⚽ Activities
|
||||
soccer: '⚽',
|
||||
basketball: '🏀',
|
||||
football: '🏈',
|
||||
baseball: '⚾',
|
||||
tennis: '🎾',
|
||||
bowling: '🎳',
|
||||
video_game: '🎮',
|
||||
chess: '♟️',
|
||||
music: '🎵',
|
||||
guitar: '🎸',
|
||||
mic: '🎤',
|
||||
|
||||
// 💡 Objects & Symbols
|
||||
lightbulb: '💡',
|
||||
phone: '📱',
|
||||
laptop: '💻',
|
||||
bomb: '💣',
|
||||
money: '💰',
|
||||
star2: '🌟',
|
||||
warning: '⚠️',
|
||||
check: '✅',
|
||||
x: '❌',
|
||||
question: '❓',
|
||||
exclamation: '❗',
|
||||
infinity: '♾️',
|
||||
hourglass: '⏳',
|
||||
clock: '🕒',
|
||||
|
||||
pepe: '🐸',
|
||||
troll: '😈',
|
||||
sus: '🧐',
|
||||
amongus: '🟥',
|
||||
monke: '🐵',
|
||||
chad: '🦍',
|
||||
gigachad: '💪',
|
||||
wojak: '😔',
|
||||
feelsbadman: '😞',
|
||||
feelsgoodman: '😌',
|
||||
yikes: '😬',
|
||||
clown: '🤡',
|
||||
clownworld: '🌎🤡',
|
||||
triggered: '😡',
|
||||
pog: '😲',
|
||||
kek: '🤣',
|
||||
based: '😎',
|
||||
cringe: '😖',
|
||||
dab: '🕺',
|
||||
sigma: '🧠',
|
||||
npc: '🤖',
|
||||
doomer: '🌑',
|
||||
zoomer: '⚡',
|
||||
boomer: '👴',
|
||||
sheesh: '😤',
|
||||
rickroll: '🕺🎶',
|
||||
trolled: '🧌',
|
||||
rekt: '💀',
|
||||
skillissue: '📉',
|
||||
bro: '🙄',
|
||||
cope: '😢',
|
||||
ratio: '➗',
|
||||
amogus: '👁️👄👁️',
|
||||
|
||||
};
|
||||
|
||||
// Escape HTML first
|
||||
let html = markdown
|
||||
.replace(/&/g, '&')
|
||||
.replace(/</g, '<')
|
||||
.replace(/>/g, '>');
|
||||
|
||||
// Code blocks (```...```)
|
||||
html = html.replace(/```([^```]*)```/gs, (match, p1) =>
|
||||
`<pre><code>${p1.trim()}</code></pre>`
|
||||
);
|
||||
|
||||
// Inline code (`code`)
|
||||
html = html.replace(/`([^`\n]+)`/g, (match, p1) => `<code>${p1}</code>`);
|
||||
|
||||
// Emojis :emoji_name:
|
||||
html = html.replace(/:([a-z0-9_]+):/gi, (match, p1) => emojiMap[p1] || match);
|
||||
|
||||
// Process overlapping formatting in order: Bold+Underline+Italic
|
||||
html = parseFormatting(html);
|
||||
|
||||
// Replace line breaks
|
||||
html = html.replace(/\n/g, '<br>');
|
||||
|
||||
return html;
|
||||
}
|
||||
|
||||
// Parse overlapping formatting using tokens
|
||||
function parseFormatting(text) {
|
||||
// Define replacement tokens and their HTML
|
||||
const formattingRules = [
|
||||
{ regex: /\*\*\*(.*?)\*\*\*/g, html: '<strong><em>$1</em></strong>' }, // ***bold italic***
|
||||
{ regex: /___(.*?)___/g, html: '<u><em>$1</em></u>' }, // ___underline italic___
|
||||
{ regex: /\*\*(.*?)\*\*/g, html: '<strong>$1</strong>' }, // **bold**
|
||||
{ regex: /__(.*?)__/g, html: '<u>$1</u>' }, // __underline__
|
||||
{ regex: /\*(.*?)\*/g, html: '<em>$1</em>' }, // *italic*
|
||||
{ regex: /_(.*?)_/g, html: '<em>$1</em>' }, // _italic_
|
||||
{ regex: /~~(.*?)~~/g, html: '<s>$1</s>' } // ~~strike~~
|
||||
];
|
||||
|
||||
// Apply formatting in order
|
||||
for (const rule of formattingRules) {
|
||||
text = text.replace(rule.regex, rule.html);
|
||||
}
|
||||
|
||||
return text;
|
||||
}
|
||||
|
||||
|
||||
// Handle incoming messages
|
||||
function handleMessage(event) {
|
||||
if (event.data === "ping") {
|
||||
|
@ -618,7 +837,7 @@ function addChatMessage(author, content, isHistory = false) {
|
|||
// Add message text
|
||||
const textDiv = document.createElement('div');
|
||||
textDiv.className = 'message-text';
|
||||
textDiv.textContent = content;
|
||||
textDiv.innerHTML = markdownToHtmlDiv(content);
|
||||
contentDiv.appendChild(textDiv);
|
||||
|
||||
messageWrapper.appendChild(avatar);
|
||||
|
@ -797,6 +1016,8 @@ async function uploadFile() {
|
|||
const formData = new FormData();
|
||||
formData.append("file", fileInput.files[0]);
|
||||
formData.append("room", currentRoom);
|
||||
formData.append("username", username);
|
||||
formData.append("token", md5(password));
|
||||
|
||||
try {
|
||||
const response = await fetch(getUploadUrl(), {
|
||||
|
@ -807,17 +1028,6 @@ async function uploadFile() {
|
|||
|
||||
if (response.ok) {
|
||||
hideFileUpload();
|
||||
|
||||
const processedMessage = {
|
||||
"type": "message",
|
||||
"username": username,
|
||||
"token": md5(password),
|
||||
"room": currentRoom,
|
||||
"content": `Sent a file`
|
||||
}
|
||||
if (ws && ws.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify(processedMessage));
|
||||
}
|
||||
} else {
|
||||
alert("Failed to upload file. Please try again.");
|
||||
}
|
||||
|
@ -1143,4 +1353,4 @@ if (uploadField) {
|
|||
this.value = "";
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -798,6 +798,20 @@ fun main(args: Array<String>) {
|
|||
Files.copy(uploadedFile.content(), filePath)
|
||||
|
||||
val room = if (ctx.formParam("room") != null) ctx.formParam("room") else "general"
|
||||
var username: String = ""
|
||||
var token: String = ""
|
||||
|
||||
if (ctx.formParam("username") != null) {
|
||||
username = ctx.formParam("username").toString()
|
||||
} else {
|
||||
// do error
|
||||
}
|
||||
|
||||
if (ctx.formParam("token") != null) {
|
||||
token = ctx.formParam("token").toString()
|
||||
} else {
|
||||
// do error
|
||||
}
|
||||
|
||||
val processedData = JSONObject().apply {
|
||||
put("type", "fileStatus")
|
||||
|
@ -808,7 +822,7 @@ fun main(args: Array<String>) {
|
|||
|
||||
val processedData2 = JSONObject().apply {
|
||||
put("type", "file")
|
||||
put("username", "system")
|
||||
put("username", username)
|
||||
put("room", room)
|
||||
put("content", "https://maxwellj.xyz/chookchat/uploads/$newFilename")
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user