Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
260 changes: 258 additions & 2 deletions webui-src/app/chat/chat.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,12 @@ const Message = () => {
};
};

const emojiList = [
'😀', '😃', '😄', '😁', '😆', '😅', '😂', '🤣', '😊', '😇',
'🙂', '🙃', '😉', '😌', '😍', '🥰', '😘', '😗', '😙', '😚',
'👍', '👎', '❤️', '👋', '🎉', '🔥', '👏', '🙏', '🤔', '💯'
];

const ChatLobbyModel = {
currentLobby: {
lobby_name: '...',
Expand Down Expand Up @@ -240,6 +246,75 @@ const ChatLobbyModel = {
'}'
);
},
sendAttachment(file, onsuccess) {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target.result;
rs.rsJsonApiRequest(
'/rsmsgs/sendChatAttachment',
{},
() => {
onsuccess();
},
true,
{},
undefined,
() =>
'{"id":{"type": 3,"lobby_id":' +
m.route.param('lobby') +
'}, "attachment":' +
JSON.stringify(data) +
'}'
);
};
reader.readAsDataURL(file);
},
sendImage(file, onsuccess) {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target.result;
rs.rsJsonApiRequest(
'/rsmsgs/sendChatImage',
{},
() => {
onsuccess();
},
true,
{},
undefined,
() =>
'{"id":{"type": 3,"lobby_id":' +
m.route.param('lobby') +
'}, "image":' +
JSON.stringify(data) +
'}'
);
};
reader.readAsDataURL(file);
},
sendSticker(file, onsuccess) {
const reader = new FileReader();
reader.onload = (e) => {
const data = e.target.result;
rs.rsJsonApiRequest(
'/rsmsgs/sendChatSticker',
{},
() => {
onsuccess();
},
true,
{},
undefined,
() =>
'{"id":{"type": 3,"lobby_id":' +
m.route.param('lobby') +
'}, "sticker":' +
JSON.stringify(data) +
'}'
);
};
reader.readAsDataURL(file);
},
selected(info, selName, defaultName) {
const currid = (ChatLobbyModel.currentLobby.lobby_id || { xstr64: m.route.param('lobby') })
.xstr64;
Expand Down Expand Up @@ -413,6 +488,10 @@ const Layout = () => {
};

const LayoutSingle = () => {
let currentFont = 'Arial';
let currentFontSize = '14px';
let currentColor = '#000000';

return {
oninit: () => ChatLobbyModel.loadLobby(m.route.param('lobby')),
view: (vnode) =>
Expand All @@ -426,15 +505,192 @@ const LayoutSingle = () => {
{},
m('textarea.chatMsg', {
placeholder: 'enter new message and press return to send',
style: {
fontFamily: currentFont,
fontSize: currentFontSize,
color: currentColor,
},
onkeydown: (e) => {
if (e.code === 'Enter') {
const msg = e.target.value;
e.target.value = ' sending ... ';
ChatLobbyModel.sendMessage(msg, () => (e.target.value = ''));
ChatLobbyModel.sendMessage(msg, () => {
e.target.value = '';
e.target.style.fontFamily = currentFont;
e.target.style.fontSize = currentFontSize;
e.target.style.color = currentColor;
});
return false;
}
},
})
}),
m('.emojiContainer', [
m('button.chatButton', {
class: 'emojiButton',
title: 'Send emoji', // Tooltip for emoji button
onclick: () => {
const emojiPicker = document.querySelector('.emojiPicker');
emojiPicker.style.display = emojiPicker.style.display === 'none' ? 'block' : 'none';
},
}, m('img', {
src: "https://i.pinimg.com/736x/e4/47/1f/e4471fd12da05d58e102f8acee595162.jpg", alt: 'Emoji'})),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do not use an external resource. This can break the anonymity of Tor nodes because i.pinimg.com will get your IP when you perform the request.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okk sir, I will change it.

m('button.chatButton', {
class: 'attachButton',
title: 'Send attachments', // Tooltip for attach button
onclick: () => {
const attachmentInput = document.querySelector('.chatAttachment');
attachmentInput.click();
},
}, m('img', { src: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcQQ6k7KXoSJ7iY0HurPvwJsx_g59l6xS5ltOQ&s", alt: 'Attach' })), // Ensure the path is correct
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

m('input[type=file].chatAttachment', {
class: 'chatAttachment',
style: { display: 'none' },
onchange: (e) => {
const file = e.target.files[0];
ChatLobbyModel.sendAttachment(file, () => (e.target.value = ''));
},
}),
m('button.chatButton', {
class: 'attachImageButton',
title: 'Send images', // Tooltip for attach image button
onclick: () => {
const imageInput = document.querySelector('.chatImage');
imageInput.click();
},
}, m('img', { src: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcS8CL7x349Zm-bhbVmAOo_p5T7m9AdSkfGb0Q&s", alt: 'Attach Image' })), // Ensure the path is correct
m('input[type=file].chatImage', {
class: 'chatImage',
style: { display: 'none' },
accept: ".jpg,.jpeg,.png,.gif,.tiff,.bmp,.svg", // Restrict file types
onchange: (e) => {
const file = e.target.files[0];
if (file && /\.(jpg|jpeg|png|gif|tiff|bmp|svg)$/i.test(file.name)) {
ChatLobbyModel.sendImage(file, () => (e.target.value = ''));
} else {
alert('Invalid file type. Please select an image file.');
e.target.value = '';
}
},
}),
m('button.chatButton', {
class: 'attachStickers',
title: 'Send stickers', // Tooltip for attach sticker button
onclick: () => {
const stickerInput = document.querySelector('.chatSticker');
stickerInput.click();
},
}, m('img', { src: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcTa2BFy825nwrflMIedj4w37yD5auVW2iVe3g", alt: 'Send Sticker', width: "20px", height: "20px" })), // Added sticker button with specified dimensions
m('input[type=file].chatSticker', {
class: 'chatSticker',
style: { display: 'none' },
onchange: (e) => {
const file = e.target.files[0];
ChatLobbyModel.sendSticker(file, () => (e.target.value = ''));
},
}),
m('button.chatButton', {
class: 'textFormatButton',
title: 'Change text font,size or color', // Tooltip for text format button
onclick: () => {
console.log('Text format button clicked');
const textFormatPicker = document.querySelector('.textFormatPicker');
console.log('Before toggle:', textFormatPicker.style.display);
textFormatPicker.style.display = textFormatPicker.style.display === 'none' ? 'block' : 'none';
console.log('After toggle:', textFormatPicker.style.display);
},
}, m('img', { src: "https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRwk0UXL-b5TnWB_OzttDO5HR844c5kOuX7Frmu9m3xf6DakgTqzErFoRVGNZxvCy37Sdw&usqp=CAU", alt: 'Text Format',height:'20px',width:'20px' })), // Added text format button with specified dimensions
m('button.chatButton', {
class: 'sendButton',
title: 'Send message', // Tooltip for send button
style: { marginLeft: 'auto' }, // Added margin-left: auto to send button
onclick: () => {
const textarea = document.querySelector('.chatMsg');
const msg = textarea.value;
textarea.value = ' sending ... ';
ChatLobbyModel.sendMessage(msg, () => {
textarea.value = '';
textarea.style.fontFamily = currentFont;
textarea.style.fontSize = currentFontSize;
textarea.style.color = currentColor;
});
},
}, m('img', {
src: "https://cdn-icons-png.flaticon.com/512/736/736110.png", alt: 'Send Message', width: "20px", height: "20px" })), // Added send button with specified dimensions
]),
m('.emojiPicker', { class: 'emojiPicker', style: { display: 'none', flexWrap: 'nowrap', overflowX: 'auto' } },
emojiList.map(emoji =>
m('span.emoji', {
onclick: () => {
const textarea = document.querySelector('.chatMsg');
textarea.value += emoji;
textarea.style.fontFamily = currentFont;
textarea.style.fontSize = currentFontSize;
textarea.style.color = currentColor;
}
}, emoji)
)
),
m('.textFormatPicker', { class: 'textFormatPicker', style: { display: 'none' } }, [
m('label', 'Font:'),
m('select', {
onchange: (e) => {
currentFont = e.target.value;
const textarea = document.querySelector('.chatMsg');
textarea.style.fontFamily = currentFont;
}
}, [
m('option', { value: 'Arial' }, 'Arial'),
m('option', { value: 'Arial Black' }, 'Arial Black'),
m('option', { value: 'Verdana' }, 'Verdana'),
m('option', { value: 'Tahoma' }, 'Tahoma'),
m('option', { value: 'Trebuchet MS' }, 'Trebuchet MS'),
m('option', { value: 'Impact' }, 'Impact'),
m('option', { value: 'Times New Roman' }, 'Times New Roman'),
m('option', { value: 'Georgia' }, 'Georgia'),
m('option', { value: 'Garamond' }, 'Garamond'),
m('option', { value: 'Courier New' }, 'Courier New'),
m('option', { value: 'Brush Script MT' }, 'Brush Script MT'),
m('option', { value: 'Lucida Console' }, 'Lucida Console'),
m('option', { value: 'Lucida Sans' }, 'Lucida Sans'),
m('option', { value: 'Palatino Linotype' }, 'Palatino Linotype'),
m('option', { value: 'Book Antiqua' }, 'Book Antiqua'),
m('option', { value: 'Franklin Gothic Medium' }, 'Franklin Gothic Medium'),
m('option', { value: 'Comic Sans MS' }, 'Comic Sans MS'),
m('option', { value: 'Century Gothic' }, 'Century Gothic'),
m('option', { value: 'Segoe UI' }, 'Segoe UI'),
m('option', { value: 'Roboto' }, 'Roboto'),
m('option', { value: 'Open Sans' }, 'Open Sans'),
m('option', { value: 'Lato' }, 'Lato'),
m('option', { value: 'Montserrat' }, 'Montserrat'),
m('option', { value: 'Raleway' }, 'Raleway'),
m('option', { value: 'Poppins' }, 'Poppins'),
m('option', { value: 'Nunito' }, 'Nunito'),
m('option', { value: 'Oswald' }, 'Oswald'),
m('option', { value: 'Ubuntu' }, 'Ubuntu'),
m('option', { value: 'Fira Sans' }, 'Fira Sans'),
m('option', { value: 'Merriweather' }, 'Merriweather')
]),
m('label', 'Size:'),
m('input[type=number]', {
min: 8,
max: 72,
value: 14,
onchange: (e) => {
currentFontSize = e.target.value + 'px';
const textarea = document.querySelector('.chatMsg');
textarea.style.fontSize = currentFontSize;
}
}),
m('label', 'Color:'),
m('input[type=color]', {
value: '#000000',
onchange: (e) => {
currentColor = e.target.value;
const textarea = document.querySelector('.chatMsg');
textarea.style.color = currentColor;
}
})
])
),
]),
};
Expand Down
73 changes: 73 additions & 0 deletions webui-src/app/scss/pages/_chat.scss
Original file line number Diff line number Diff line change
Expand Up @@ -162,3 +162,76 @@ textarea.chatMsg {
.createDistantChat {
margin-top: 1em;
}

.chatButton {
background: none;
border: none;
cursor: pointer;
font-size: 1.5em;
margin-left: 10px; /* Add some space between the buttons */
}

.sendButton img,
.attachButton img,
.attachImageButton img {
width: 20px;
height: 20px;
}

.emojiButton img {
width: 20px;
height: 20px;
background-color: white;
}

.emojiPicker {
position: absolute;
bottom: 50px;
left: 10px;
background: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-wrap: wrap;
gap: 5px;
}

.emojiPicker .emoji {
cursor: pointer;
font-size: 1em;
}

.emojiContainer {
display: flex;
justify-content: flex-start;
background-color: white;
// padding: 0px;
// border-top: 1px solid #ccc;
}

.textFormatPicker {
position: absolute;
bottom: 50px;
right: 10px;
background: white;
border: 1px solid #ccc;
padding: 10px;
border-radius: 5px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
display: flex;
flex-direction: column;
gap: 10px;
}

.textFormatPicker label {
font-size: 0.9em;
margin-bottom: 5px;
}

.textFormatPicker select,
.textFormatPicker input[type="number"],
.textFormatPicker input[type="color"] {
margin-bottom: 10px;
}
2 changes: 1 addition & 1 deletion webui-src/styles.css

Large diffs are not rendered by default.