275 lines
6 KiB
Svelte
275 lines
6 KiB
Svelte
<script>
|
||
import Header from '../Header.svelte';
|
||
import { onMount } from 'svelte';
|
||
import Time from 'svelte-time';
|
||
import { dayjs } from 'svelte-time';
|
||
import 'dayjs/locale/ru';
|
||
import { UserCheck, getLastMessages, MessagePicToUrl } from '$lib/userFunction.js';
|
||
import createWebSocket from '$lib/websocket';
|
||
|
||
dayjs.locale('ru');
|
||
console.clear();
|
||
|
||
let userId; //пользователь, который залогинен
|
||
let socket; //вебсокет
|
||
|
||
let messages = []; //массив сообщений, которые отображаются на сайте
|
||
let messageText = ''; //сообщения для отправки
|
||
let messagePic; //картинка для отправки
|
||
|
||
onMount(async () => {
|
||
const userData = await UserCheck();
|
||
let userId = userData.id;
|
||
let chatId = 2;
|
||
const websocketUrl = `ws://localhost:8000/api/chat/ws/${chatId}?user_id=${userId}`;
|
||
|
||
messages = await getLastMessages();
|
||
|
||
socket = createWebSocket(websocketUrl, (message) => {
|
||
messages = [message, ...messages];
|
||
});
|
||
});
|
||
|
||
async function uploadImages() {
|
||
const fileInput = document.getElementById('file');
|
||
const file = fileInput.files[0];
|
||
let urlpic;
|
||
if (file) {
|
||
urlpic = await MessagePicToUrl(file);
|
||
} else {
|
||
urlpic = null;
|
||
}
|
||
fileInput.value = null;
|
||
return urlpic;
|
||
}
|
||
|
||
async function sendMessage() {
|
||
let messageUrl = await uploadImages();
|
||
|
||
if (messageText.trim() !== '' || messageUrl != null) {
|
||
socket.send(JSON.stringify({ message: messageText, image_url: messageUrl }));
|
||
messageText = null;
|
||
}
|
||
}
|
||
|
||
let textarea;
|
||
|
||
const updateTextareaSize = () => {
|
||
// Устанавливаем высоту textarea на основе количества строк
|
||
textarea.style.height = 'auto'; // Сбрасываем высоту на auto перед измерением
|
||
textarea.style.height = `${textarea.scrollHeight}px`;
|
||
|
||
};
|
||
|
||
function handleKeyPress(event) {
|
||
if (event.key === 'Enter' && !event.shiftKey) {
|
||
// Если нажат Enter и не нажат Shift, отправляем сообщение
|
||
sendMessage(event);
|
||
}
|
||
}
|
||
</script>
|
||
|
||
<body class="backgroundPic">
|
||
<div class="DivHeader"><Header /></div>
|
||
<div>жопа2</div>
|
||
<div class="divChat">
|
||
<div class="chatBox">
|
||
{#each messages as message}
|
||
<div class="MsgAll">
|
||
<img class="MsgAva" src={message.avatar_image} alt="ава" />
|
||
<div class="divMessage">
|
||
<div class="userFiled">
|
||
<h3 class="MsgName">{message.username}</h3>
|
||
<Time relative timestamp={message.created_at}></Time>
|
||
</div>
|
||
|
||
<p class="MsgMsg">{message.message}</p>
|
||
|
||
{#if message.image_url != null}
|
||
<img class="MsgPic" src={message.image_url} alt="" />
|
||
{/if}
|
||
</div>
|
||
</div>
|
||
{/each}
|
||
</div>
|
||
|
||
<form class="chatSend" on:submit={sendMessage}>
|
||
<textarea
|
||
class="chatInput"
|
||
placeholder="Введите сообщение"
|
||
maxlength="2000"
|
||
rows="3"
|
||
bind:this={textarea}
|
||
on:input={updateTextareaSize}
|
||
type="text"
|
||
bind:value={messageText}
|
||
on:keypress={handleKeyPress}
|
||
></textarea>
|
||
<div class="fileInputDiv">
|
||
<input name="file" id="file" type="file" accept="image/*" bind:value={messagePic} />
|
||
<label class="attachingImages" for="file"><img src="./attachment.svg" alt=""></label>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
<div>жопа4</div>
|
||
<div>жопа5</div>
|
||
<div>жопа6</div>
|
||
<div>жопа7</div>
|
||
</body>
|
||
|
||
<style>
|
||
|
||
.fileInputDiv{
|
||
background-color: rgba(255, 255, 255, 0.1);
|
||
border-bottom-right-radius: 15px;
|
||
}
|
||
|
||
.attachingImages{
|
||
display: flex;
|
||
justify-content: center;
|
||
width: 5vh;
|
||
height: 5vh;
|
||
min-width: 30px;
|
||
min-height: 30px;
|
||
padding: 10px;
|
||
|
||
}
|
||
|
||
#file{
|
||
display: none;
|
||
}
|
||
|
||
.userFiled {
|
||
display: flex;
|
||
justify-content: flex-start;
|
||
}
|
||
|
||
.MsgMsg{
|
||
|
||
}
|
||
|
||
.MsgName {
|
||
|
||
}
|
||
|
||
.MsgPic {
|
||
margin-left: 1vw;
|
||
margin-bottom: 1vh;
|
||
width: 80%;
|
||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||
border-radius: 15px;
|
||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.9);
|
||
}
|
||
|
||
.MsgAva {
|
||
height: 6vh;
|
||
min-height: 50px;
|
||
width: auto;
|
||
border: 2px solid rgba(255, 255, 255, 0.6);
|
||
border-radius: 10px;
|
||
margin: 0.25vw;
|
||
}
|
||
|
||
.MsgAll {
|
||
display:flex;
|
||
flex-direction: row;
|
||
|
||
}
|
||
|
||
.divMessage {
|
||
background-color: rgba(255, 255, 255, 0.3);
|
||
border: 1px solid rgba(255, 255, 255, 0.5);
|
||
border-radius: 15px;
|
||
box-shadow: 0 0px 30px rgba(0, 0, 0, 0.2);
|
||
|
||
|
||
margin: 3px;
|
||
overflow-wrap: break-word;
|
||
|
||
}
|
||
|
||
.chatBox {
|
||
display: flex;
|
||
flex: 30;
|
||
flex-direction: column-reverse;
|
||
align-items: flex-start;
|
||
|
||
overflow-x:hidden;
|
||
width: 100%;
|
||
|
||
|
||
/* From https://css.glass */
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
border-radius: 15px;
|
||
border-bottom-left-radius: 0;
|
||
border-bottom-right-radius: 0;
|
||
box-shadow: 0 -4px 30px rgb(0, 0, 0, 0.5);
|
||
|
||
backdrop-filter: blur(7px);
|
||
border: 1px solid rgba(255, 255, 255, 0.43);
|
||
}
|
||
|
||
.DivHeader {
|
||
grid-column: 3 span;
|
||
border: 0 !important;
|
||
margin: 0;
|
||
padding: 0;
|
||
z-index: 2;
|
||
}
|
||
|
||
.chatSend {
|
||
box-shadow: 0 -4px 30px rgb(0, 0, 0, 0.5);
|
||
display: flex;
|
||
flex: 2;
|
||
width: 100%;
|
||
justify-content: space-between;
|
||
border: 1px solid rgba(255, 255, 255, 0.43);
|
||
border-bottom-left-radius: 15px;
|
||
border-bottom-right-radius: 15px;
|
||
}
|
||
|
||
.chatInput {
|
||
|
||
outline: none;
|
||
width: 100%;
|
||
resize: none;
|
||
box-sizing: border-box;
|
||
background-color: rgba(255, 255, 255, 0.2);
|
||
border: transparent solid;
|
||
max-height: 12em;
|
||
border-bottom-left-radius: 15px;
|
||
|
||
}
|
||
|
||
.divChat {
|
||
flex-direction: column;
|
||
display: flex;
|
||
|
||
}
|
||
|
||
body {
|
||
display: grid;
|
||
grid-template-columns: 25vw 50vw 25vw; /* 2 колонки с равным распределением ширины */
|
||
grid-template-rows: 10vh 80vh 10vh;
|
||
}
|
||
|
||
body > * {
|
||
/* border: 1px solid black; */
|
||
}
|
||
|
||
* {
|
||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||
}
|
||
|
||
.backgroundPic {
|
||
grid-column: span 3;
|
||
grid-row: span 3;
|
||
|
||
background-color: #7a5abd;
|
||
background-image: url(./BPytka.png);
|
||
background-repeat: no-repeat;
|
||
background-size: 50vh;
|
||
background-position-x: 50%;
|
||
background-position-y: 50%;
|
||
}
|
||
</style>
|