все кроме редактирования есть
This commit is contained in:
parent
a2fd7f7318
commit
5f94ff5e29
9 changed files with 810 additions and 356 deletions
10
package-lock.json
generated
10
package-lock.json
generated
|
@ -11,6 +11,7 @@
|
|||
"@sveltestrap/sveltestrap": "^6.2.4",
|
||||
"@themesberg/flowbite": "^1.3.0",
|
||||
"cropperjs": "^1.6.2",
|
||||
"date-fns": "^3.6.0",
|
||||
"sass": "^1.70.0",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5",
|
||||
|
@ -1626,6 +1627,15 @@
|
|||
"type": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"node_modules/date-fns": {
|
||||
"version": "3.6.0",
|
||||
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
|
||||
"integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
|
||||
"funding": {
|
||||
"type": "github",
|
||||
"url": "https://github.com/sponsors/kossnocorp"
|
||||
}
|
||||
},
|
||||
"node_modules/dayjs": {
|
||||
"version": "1.11.10",
|
||||
"resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz",
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
"@sveltestrap/sveltestrap": "^6.2.4",
|
||||
"@themesberg/flowbite": "^1.3.0",
|
||||
"cropperjs": "^1.6.2",
|
||||
"date-fns": "^3.6.0",
|
||||
"sass": "^1.70.0",
|
||||
"socket.io": "^4.7.5",
|
||||
"socket.io-client": "^4.7.5",
|
||||
|
|
19
src/app.html
19
src/app.html
|
@ -87,7 +87,15 @@
|
|||
background: transparent;
|
||||
border: 0;
|
||||
height: 10%;
|
||||
transition: 0.15s ease-in;
|
||||
}
|
||||
|
||||
button:disabled{
|
||||
color: rgba(255, 255, 255, 0.329);
|
||||
text-shadow: 0 0 20px rgba(0, 0, 0, 0.322);
|
||||
}
|
||||
|
||||
|
||||
button,
|
||||
select,
|
||||
option {
|
||||
|
@ -169,5 +177,16 @@
|
|||
border-radius: 15px;
|
||||
}
|
||||
|
||||
.backgroundBlur{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
</style>
|
||||
</html>
|
||||
|
|
|
@ -1,4 +1,7 @@
|
|||
export async function getLastMessages(chatId,msgLoaded){
|
||||
// import formatDistanceToNow from 'date-fns/formatDistanceToNow';
|
||||
// import ruLocale from 'date-fns/locale/ru';
|
||||
|
||||
export async function getLastMessages(chatId,msgLoaded){
|
||||
|
||||
let token = localStorage.getItem('BPChat')
|
||||
const response = await fetch(`https://docs.black-phoenix.ru/api/chat/get_some_messages/${chatId}?messages_loaded=${msgLoaded}&messages_to_get=15`,
|
||||
|
@ -20,12 +23,16 @@
|
|||
}
|
||||
else{
|
||||
msgMassive.reverse();
|
||||
let utc = msgMassive[0].created_at
|
||||
console.log(utc)
|
||||
let newutc = new Date(utc)
|
||||
console.log(utc)
|
||||
console.log(newutc)
|
||||
|
||||
// for(let i = 0; i < msgMassive.length; i++){
|
||||
// let utc = msgMassive[i].created_at
|
||||
// let newutc = new Date(utc)
|
||||
// //console.log(utc)
|
||||
// const formattedDate = formatDistanceToNow(new Date(newutc), { addSuffix: true, locale: ruLocale });
|
||||
// //console.log(newutc)
|
||||
// console.log(formattedDate)
|
||||
// msgMassive[i].created_at = formattedDate
|
||||
// }
|
||||
return msgMassive
|
||||
}
|
||||
}
|
||||
|
@ -176,3 +183,57 @@
|
|||
}
|
||||
}
|
||||
|
||||
export async function getAllUsers(nameToFind){
|
||||
|
||||
const response = await fetch(`https://docs.black-phoenix.ru/api/users?username=${nameToFind}`,{
|
||||
method:"GET",
|
||||
credentials:'include'
|
||||
})
|
||||
|
||||
if(response.ok){
|
||||
let data = await response.json()
|
||||
let anotherData = data.users
|
||||
|
||||
if(anotherData == null){
|
||||
return []
|
||||
}
|
||||
return data.users
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export async function createNewChat(chatName, excludeUser, token){
|
||||
console.log(token, "token")
|
||||
const response = await fetch(`https://docs.black-phoenix.ru/api/chat/create_chat?user_to_exclude=${excludeUser}&chat_name=${chatName}`,{
|
||||
method: 'POST',
|
||||
credentials: 'include',
|
||||
headers: {'Authorization': token },
|
||||
})
|
||||
|
||||
if(response.ok){
|
||||
let data = await response.json()
|
||||
let id = data.chat_id
|
||||
return id
|
||||
}
|
||||
else{
|
||||
console.log(response)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
export async function deleteChat(chatId, token){
|
||||
|
||||
const response = await fetch(`https://docs.black-phoenix.ru/api/chat/delete_chat/${chatId}`,{
|
||||
method: 'DELETE',
|
||||
credentials: 'include',
|
||||
headers: {'Authorization': token },
|
||||
})
|
||||
|
||||
if(response.ok){
|
||||
return "Чат удален"
|
||||
}
|
||||
|
||||
else{
|
||||
console.log(response)
|
||||
}
|
||||
}
|
|
@ -1,89 +1,46 @@
|
|||
// import io from 'socket.io-client';
|
||||
export default function createWebSocket(url, token, onMessageCallback, maxRetries = 10) {
|
||||
let socket;
|
||||
let retries = 0;
|
||||
let messageQueue = [];
|
||||
token = token.split(" ")[1];
|
||||
|
||||
// export default function createWebSocket(url, token, onMessageCallback) {
|
||||
// const socket = io(url, {
|
||||
// auth: {
|
||||
// token: "123"
|
||||
// },
|
||||
// //withCredentials: true,
|
||||
// });
|
||||
function connect() {
|
||||
socket = new WebSocket(url, [token]);
|
||||
|
||||
// socket.on('message', (message) => {
|
||||
// console.log('Получено сообщение:', message);
|
||||
// });
|
||||
socket.addEventListener('message', (event) => {
|
||||
const jsonData = JSON.parse(event.data)
|
||||
onMessageCallback(jsonData)
|
||||
});
|
||||
|
||||
// function sendMessage(message) {
|
||||
// socket.emit('message', message);
|
||||
// }
|
||||
socket.onopen = () => {
|
||||
console.log('WebSocket is open now.')
|
||||
retries = 0 //сброс попыток
|
||||
|
||||
// return socket;
|
||||
// }
|
||||
while (messageQueue.length > 0) {
|
||||
socket.send(messageQueue.shift());
|
||||
}
|
||||
};
|
||||
|
||||
// export default function createWebSocket(url, token , onMessageCallback) {
|
||||
socket.onclose = (event) => {
|
||||
console.log('WebSocket is closed now.', event)
|
||||
if (retries < maxRetries) {
|
||||
retries++
|
||||
const timeout = Math.min(1000 * Math.pow(2, retries), 30000)
|
||||
setTimeout(() => {
|
||||
console.log(`Reconnecting... attempt ${retries}`)
|
||||
connect()
|
||||
}, timeout)
|
||||
} else {
|
||||
console.log('Max retries reached. Could not reconnect.')
|
||||
}
|
||||
};
|
||||
|
||||
// const socket = new WebSocket(url, {
|
||||
// headers:{ Authorization: token }
|
||||
// })
|
||||
|
||||
// socket.addEventListener('message', (event) => {
|
||||
// const jsonData = JSON.parse(event.data);
|
||||
// onMessageCallback(jsonData);
|
||||
// //console.log(jsonData)
|
||||
// });
|
||||
|
||||
// return socket;
|
||||
// }
|
||||
|
||||
// import SockJS from 'sockjs-client';
|
||||
|
||||
// export default function createWebSocket(url,token , onMessageCallback) {
|
||||
// const sock = new SockJS(url, null, {
|
||||
// headers: {
|
||||
// 'Authorization': token
|
||||
// }
|
||||
// });
|
||||
|
||||
// //socket.onmessage = (event) => {
|
||||
// // const jsonData = JSON.parse(event.data);
|
||||
// // onMessageCallback(jsonData);
|
||||
// // //console.log(jsonData)
|
||||
// //};
|
||||
|
||||
// sock.onopen = function() {
|
||||
// console.log('open');
|
||||
// sock.send('test');
|
||||
// };
|
||||
|
||||
// sock.onmessage = function(e) {
|
||||
// console.log('message', e.data);
|
||||
// sock.close();
|
||||
// };
|
||||
|
||||
// sock.onclose = function() {
|
||||
// console.log('close');
|
||||
// };
|
||||
|
||||
// return sock;
|
||||
// }
|
||||
|
||||
export default function createWebSocket(url, token, onMessageCallback) {
|
||||
token = token.split(" ")[1]
|
||||
//console.log(token)
|
||||
const socket = new WebSocket(url, [token])
|
||||
|
||||
socket.addEventListener('message', (event) => {
|
||||
const jsonData = JSON.parse(event.data);
|
||||
onMessageCallback(jsonData);
|
||||
//console.log(jsonData)S
|
||||
});
|
||||
|
||||
socket.onopen = (event) => {
|
||||
console.log('WebSocket is open now.');
|
||||
};
|
||||
|
||||
socket.addEventListener('close', (event) =>{
|
||||
console.log(event)
|
||||
})
|
||||
|
||||
return socket;
|
||||
socket.onerror = (error) => {
|
||||
console.error('WebSocket error observed:', error)
|
||||
};
|
||||
}
|
||||
|
||||
connect()
|
||||
|
||||
return socket
|
||||
}
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
<script>
|
||||
|
||||
import { fade, slide, fly, scale } from 'svelte/transition';
|
||||
import { onMount } from 'svelte';
|
||||
import Select from 'svelte-select';
|
||||
|
||||
|
@ -38,8 +40,8 @@
|
|||
<div><img class="userAvatar" src={userImage} alt="аватарка"/></div>
|
||||
</button>
|
||||
|
||||
{#if isOpen}
|
||||
<div class="dropdown">
|
||||
{#if isOpen }
|
||||
<div class="dropdown" transition:slide={{ duration: 300, delay: 150 }}>
|
||||
<a href="/profile" class="listItem">Профиль</a>
|
||||
<a href="/settings" class="listItem">Настройки</a>
|
||||
<a on:click={handleLogout} class="listItem">Выйти</a>
|
||||
|
|
|
@ -1,13 +1,17 @@
|
|||
<script>
|
||||
|
||||
import { onMount } from 'svelte';
|
||||
import { fade, slide, fly, scale } from 'svelte/transition';
|
||||
|
||||
import { getAvatarHistory, changeUserData, getConfirmationCode } from '$lib/settings'
|
||||
import { UserCheck } from '$lib/userFunction';
|
||||
import { uploadImages } from '$lib/chat';
|
||||
import Header from './../Header.svelte';
|
||||
|
||||
import Cropper from 'cropperjs';
|
||||
import 'cropperjs/dist/cropper.css';
|
||||
import { uploadImages } from '$lib/chat';
|
||||
import { blur } from 'svelte/transition';
|
||||
import Header from './../Header.svelte';
|
||||
import { UserCheck } from '$lib/userFunction';
|
||||
import { onMount } from 'svelte';
|
||||
import { getAvatarHistory, changeUserData, getConfirmationCode } from '$lib/settings'
|
||||
|
||||
let urlChecker = "https://"
|
||||
let token
|
||||
let confCode
|
||||
let userData = []
|
||||
|
@ -58,8 +62,12 @@
|
|||
}
|
||||
|
||||
async function submit(){
|
||||
newAvatar = await uploadImages(newAvatar)
|
||||
console.log(newAvatar)
|
||||
if(pickedImg != ""){
|
||||
newAvatar = pickedImg
|
||||
} else {
|
||||
newAvatar = await uploadImages(newAvatar)
|
||||
}
|
||||
|
||||
let changing = afterChanging = await changeUserData(token, newName, newEmail, newPassword, newAvatar, code)
|
||||
console.log(changing)
|
||||
if (changing == true){
|
||||
|
@ -129,22 +137,34 @@
|
|||
showCroppingImgDiv = false
|
||||
};
|
||||
|
||||
function cancelCroppedImage(){
|
||||
showCroppingImgDiv = false
|
||||
}
|
||||
|
||||
let pickedImg = ""
|
||||
function PickOldAvatar(oldAvatarUrl){
|
||||
pickedImg = oldAvatarUrl
|
||||
}
|
||||
</script>
|
||||
|
||||
<body>
|
||||
|
||||
{#if showCroppingImgDiv}
|
||||
<div class="backgroundBlur"></div>
|
||||
<div class="backgroundBlur" transition:fade={{ duration: 500 }}></div>
|
||||
|
||||
<div class="croppingDiv">
|
||||
<div class="croppingDiv" transition:fly={{y: -800, duration: 500 }}>
|
||||
<!-- svelte-ignore a11y-img-redundant-alt -->
|
||||
<img class="cropAvatar" bind:this={imageElement} alt="Image to crop" />
|
||||
<button class="cropButton" on:click={getCroppedImage}>Подтвердить</button>
|
||||
<div class="cropButtonsDiv">
|
||||
<button class="cropButton" on:click={getCroppedImage}>Подтвердить</button>
|
||||
<button class="cropButton" on:click={cancelCroppedImage}>Отменить</button>
|
||||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if showSubmitDiv}
|
||||
<div class="backgroundBlur"></div>
|
||||
<div class="submitPassword">
|
||||
<div class="backgroundBlur" transition:fade={{ duration: 500 }}></div>
|
||||
<div class="submitPassword" transition:fly={{y: -800, duration: 500 }}>
|
||||
<h2>Подтвердите кодом из почты</h2>
|
||||
<input bind:value={code} type="password" id="oldPassword" placeholder="Код">
|
||||
<button on:click={submit}>Отправить</button>
|
||||
|
@ -175,12 +195,17 @@
|
|||
{/if}
|
||||
</button>
|
||||
|
||||
<div class="avatarsHistory">
|
||||
{#each avatars as avatar}
|
||||
<img class="avatarHistory" src="{avatar.avatar_url}" alt="ава">
|
||||
{/each}
|
||||
<div class="avatarHistoryDiv">
|
||||
<h3>старые фотки</h3>
|
||||
<div class="avatarsHistory">
|
||||
{#each avatars as avatar}
|
||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
||||
<!-- svelte-ignore a11y-no-noninteractive-element-interactions -->
|
||||
<img class="avatarHistory" class:avatarHistoryPicked={avatar.avatar_url == pickedImg} src="{avatar.avatar_url}" alt="ава"
|
||||
on:click={PickOldAvatar(avatar.avatar_url)}>
|
||||
{/each}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<input type="file" accept="image/*" id="fileInput"
|
||||
on:change={handleFileChange} style="display: none;">
|
||||
</div>
|
||||
|
@ -214,11 +239,21 @@
|
|||
|
||||
<style lang="scss">
|
||||
|
||||
.cropper-modal {
|
||||
|
||||
.cropper-modal {
|
||||
background-color: #101010;
|
||||
opacity: 0.5;
|
||||
}
|
||||
|
||||
.cropButtonsDiv{
|
||||
width: 100%;
|
||||
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.cropButton{
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
@ -239,9 +274,7 @@
|
|||
|
||||
|
||||
position: absolute;
|
||||
left: 50%; top: 50%;
|
||||
transform: (-50%,-50%);
|
||||
transform: translate(-50%,-50%);
|
||||
left: 33.33%; top: 10%;
|
||||
|
||||
padding: 20px;
|
||||
max-height: 90%;
|
||||
|
@ -272,8 +305,33 @@
|
|||
.avatarHistory{
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
padding: 3px;
|
||||
|
||||
border-radius: 15px;
|
||||
padding: 3px;
|
||||
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.avatarHistoryPicked{
|
||||
width: 75px;
|
||||
height: 75px;
|
||||
|
||||
border-radius: 15px;
|
||||
padding: 1px;
|
||||
|
||||
border: 2px solid transparent;
|
||||
background:
|
||||
linear-gradient(#101010, #101010) padding-box,
|
||||
var(--gradient) border-box;
|
||||
}
|
||||
|
||||
.avatarHistoryDiv{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.changeAvatar{
|
||||
|
@ -296,17 +354,6 @@ button{
|
|||
font-size: 32px;
|
||||
}
|
||||
|
||||
.backgroundBlur{
|
||||
position: fixed;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: rgba(0, 0, 0, 0.5);
|
||||
backdrop-filter: blur(10px);
|
||||
z-index: 4;
|
||||
}
|
||||
|
||||
#oldPassword{
|
||||
justify-content: center;
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -51,8 +51,8 @@
|
|||
</script>
|
||||
|
||||
<div class="crop-container">
|
||||
<input type="file" accept="image/*" on:change={handleFileChange} />
|
||||
<img bind:this={imageElement} alt="Image to crop" />
|
||||
<input type="file" accept="image/*" id="fileInput" on:change={handleFileChange} />
|
||||
<img class="CropAvatar" bind:this={imageElement} alt="Image to crop" />
|
||||
|
||||
</div>
|
||||
<button on:click={getCroppedImage}>Crop Image</button>
|
||||
|
|
Loading…
Add table
Reference in a new issue