Version 1.1.0 - Modification et ajout de fonctionnalités
	
		
			
	
		
	
	
		
	
		
			All checks were successful
		
		
	
	
		
			
				
	
				Frontend Deployment / deploy-frontend (push) Successful in 34s
				
			
		
		
	
	
				
					
				
			
		
			All checks were successful
		
		
	
	Frontend Deployment / deploy-frontend (push) Successful in 34s
				
			This commit is contained in:
		@@ -1,6 +1,6 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  "name": "chopin-frontend",
 | 
					  "name": "chopin-frontend",
 | 
				
			||||||
  "version": "1.0.3",
 | 
					  "version": "1.1.0",
 | 
				
			||||||
  "private": true,
 | 
					  "private": true,
 | 
				
			||||||
  "scripts": {
 | 
					  "scripts": {
 | 
				
			||||||
    "dev": "vite --host --port 8080",
 | 
					    "dev": "vite --host --port 8080",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -54,6 +54,7 @@ import GuildHeaderUsers from '../Widget/Guild/GuildHeaderUsers.vue';
 | 
				
			|||||||
import GuildSettings from '../Widget/Guild/GuildSettings.vue';
 | 
					import GuildSettings from '../Widget/Guild/GuildSettings.vue';
 | 
				
			||||||
import { useUserStore } from '@/stores/userStore';
 | 
					import { useUserStore } from '@/stores/userStore';
 | 
				
			||||||
import { useGlobalStore } from '@/stores/globalStore';
 | 
					import { useGlobalStore } from '@/stores/globalStore';
 | 
				
			||||||
 | 
					import Events from '@/utils/Events';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const userStore = useUserStore();
 | 
					const userStore = useUserStore();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -109,8 +110,13 @@ function updateServerInfo() {
 | 
				
			|||||||
        console.log("Server info updated");
 | 
					        console.log("Server info updated");
 | 
				
			||||||
        events.emit("GUILD_JOINED", data);
 | 
					        events.emit("GUILD_JOINED", data);
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Events.on("GUILD_LIST_UPDATE", (guilds) => {
 | 
				
			||||||
 | 
					    server.value = guilds.find(g => g.id === globalStore.lastGuild);
 | 
				
			||||||
 | 
					});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
<style scoped>
 | 
					<style scoped>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -151,7 +151,6 @@ function onDragEnd(event) {
 | 
				
			|||||||
    display: flex;
 | 
					    display: flex;
 | 
				
			||||||
    flex-direction: column;
 | 
					    flex-direction: column;
 | 
				
			||||||
    gap: 10px;
 | 
					    gap: 10px;
 | 
				
			||||||
    padding-right: 5px;
 | 
					 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    height: 100%;
 | 
					    height: 100%;
 | 
				
			||||||
    overflow-y: auto;
 | 
					    overflow-y: auto;
 | 
				
			||||||
@@ -192,6 +191,7 @@ function onDragEnd(event) {
 | 
				
			|||||||
    gap: 10px;
 | 
					    gap: 10px;
 | 
				
			||||||
    margin-top: 2.5px;
 | 
					    margin-top: 2.5px;
 | 
				
			||||||
    margin-bottom: 2.5px;
 | 
					    margin-bottom: 2.5px;
 | 
				
			||||||
 | 
					    padding-right: 5px;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
.allSpace {
 | 
					.allSpace {
 | 
				
			||||||
    flex: 1;
 | 
					    flex: 1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,8 +1,8 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
<Video :video="video" ref="videoContainer">
 | 
					<Video :video="video" ref="videoContainer">
 | 
				
			||||||
    <div ref="controls" class="controls">
 | 
					    <div ref="controls" class="controls">
 | 
				
			||||||
        <span v-if="globalStore.currentChannel" title="Ajouter à la liste de lecture" @click="disableAction(); playSong(false)" class="control-icon"><AddList /></span>
 | 
					        <span title="Ajouter à la liste de lecture" @click="disableAction(); playSong(false)" :class="{'control-icon': globalStore.currentChannel, 'control-icon-disable': !globalStore.currentChannel}"><AddList /></span>
 | 
				
			||||||
        <span v-if="globalStore.currentChannel" title="Lire maintenant" @click="disableAction(); playSong(true)" class="control-icon"><Icon icon="fa-play" /></span>
 | 
					        <span title="Lire maintenant" @click="disableAction(); playSong(true)" :class="{'control-icon': globalStore.currentChannel, 'control-icon-disable': !globalStore.currentChannel}"><Icon icon="fa-play" /></span>
 | 
				
			||||||
        <span v-if="!props.delete && video.type != 'attachment'" title="Enregistrer dans une playlist" @click="disableAction(); saveModal.open()" class="control-icon"><Icon icon="fa-save" /></span>
 | 
					        <span v-if="!props.delete && video.type != 'attachment'" title="Enregistrer dans une playlist" @click="disableAction(); saveModal.open()" class="control-icon"><Icon icon="fa-save" /></span>
 | 
				
			||||||
        <span v-if="props.delete" title="Supprimer" @click="disableAction(); Events.emit('video:delete', { video: props.video })" class="control-icon"><Icon icon="fa-trash" /></span>
 | 
					        <span v-if="props.delete" title="Supprimer" @click="disableAction(); Events.emit('video:delete', { video: props.video })" class="control-icon"><Icon icon="fa-trash" /></span>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@@ -11,7 +11,7 @@
 | 
				
			|||||||
    <Video :video="video"/>
 | 
					    <Video :video="video"/>
 | 
				
			||||||
    <Button v-if="globalStore.currentChannel" @click="playSong(false)"><AddList /> Ajouter à la liste de lecture</Button>
 | 
					    <Button v-if="globalStore.currentChannel" @click="playSong(false)"><AddList /> Ajouter à la liste de lecture</Button>
 | 
				
			||||||
    <Button v-if="globalStore.currentChannel" @click="playSong(true)"><Icon icon="fa-solid fa-play"/> Lire maintenant</Button>
 | 
					    <Button v-if="globalStore.currentChannel" @click="playSong(true)"><Icon icon="fa-solid fa-play"/> Lire maintenant</Button>
 | 
				
			||||||
    <div v-else>
 | 
					    <div v-if="!globalStore.currentChannel" >
 | 
				
			||||||
        <p class="text-secondary">Connectez vous à un salon audio sur le serveur {{ globalStore.actualServer ? globalStore.actualServer.name : '' }}, pour lancer un titre</p>
 | 
					        <p class="text-secondary">Connectez vous à un salon audio sur le serveur {{ globalStore.actualServer ? globalStore.actualServer.name : '' }}, pour lancer un titre</p>
 | 
				
			||||||
        <ActualChannel/>
 | 
					        <ActualChannel/>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
@@ -64,6 +64,7 @@ const props = defineProps({
 | 
				
			|||||||
let nativeVideo = {}
 | 
					let nativeVideo = {}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function disableAction() {
 | 
					function disableAction() {
 | 
				
			||||||
 | 
					    if(!globalStore.currentChannel) return;
 | 
				
			||||||
    controls.value.style.display = "none";
 | 
					    controls.value.style.display = "none";
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -74,7 +75,7 @@ let activePointerId = null;
 | 
				
			|||||||
const SLIDE_THRESHOLD = 10; // ajuster si besoin
 | 
					const SLIDE_THRESHOLD = 10; // ajuster si besoin
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function playSong(now) {
 | 
					function playSong(now) {
 | 
				
			||||||
    
 | 
					    if(!globalStore.currentChannel) return;
 | 
				
			||||||
    IORequest("/SEARCH/PLAY", (data) => {
 | 
					    IORequest("/SEARCH/PLAY", (data) => {
 | 
				
			||||||
        modal.value.close();    
 | 
					        modal.value.close();    
 | 
				
			||||||
    }, {song: nativeVideo, now: now})
 | 
					    }, {song: nativeVideo, now: now})
 | 
				
			||||||
@@ -118,9 +119,12 @@ onMounted(() => {
 | 
				
			|||||||
            if (activePointerId != null) videoContainer.value.releasePointerCapture(activePointerId);
 | 
					            if (activePointerId != null) videoContainer.value.releasePointerCapture(activePointerId);
 | 
				
			||||||
        } catch (e) { /* ignore */ }
 | 
					        } catch (e) { /* ignore */ }
 | 
				
			||||||
        if(!videoContainer.value) return
 | 
					        if(!videoContainer.value) return
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
        videoContainer.value.removeEventListener('pointermove', onPointerMove);
 | 
					        videoContainer.value.removeEventListener('pointermove', onPointerMove);
 | 
				
			||||||
        videoContainer.value.removeEventListener('pointerup', onPointerUp);
 | 
					        videoContainer.value.removeEventListener('pointerup', onPointerUp);
 | 
				
			||||||
        videoContainer.value.removeEventListener('pointercancel', onPointerCancel);
 | 
					        videoContainer.value.removeEventListener('pointercancel', onPointerCancel);
 | 
				
			||||||
 | 
					        } catch (e) { console.log(videoContainer.value) }
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
        activePointerId = null;
 | 
					        activePointerId = null;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -149,10 +153,16 @@ onMounted(() => {
 | 
				
			|||||||
        isSliding = false;
 | 
					        isSliding = false;
 | 
				
			||||||
        activePointerId = ev.pointerId;
 | 
					        activePointerId = ev.pointerId;
 | 
				
			||||||
        if(!videoContainer.value) return
 | 
					        if(!videoContainer.value) return
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
 | 
					            thumbnailContainer.value = videoContainer.value.getThumbnailContainer();
 | 
				
			||||||
 | 
					            videoContainer.value = videoContainer.value.getVideoContainer();
 | 
				
			||||||
 | 
					        } catch (e) { }
 | 
				
			||||||
        try { videoContainer.value.setPointerCapture(activePointerId); } catch (e) { /* ignore */ }
 | 
					        try { videoContainer.value.setPointerCapture(activePointerId); } catch (e) { /* ignore */ }
 | 
				
			||||||
 | 
					        try {
 | 
				
			||||||
             videoContainer.value.addEventListener('pointermove', onPointerMove);
 | 
					             videoContainer.value.addEventListener('pointermove', onPointerMove);
 | 
				
			||||||
            videoContainer.value.addEventListener('pointerup', onPointerUp);
 | 
					            videoContainer.value.addEventListener('pointerup', onPointerUp);
 | 
				
			||||||
            videoContainer.value.addEventListener('pointercancel', onPointerCancel);
 | 
					            videoContainer.value.addEventListener('pointercancel', onPointerCancel);
 | 
				
			||||||
 | 
					        } catch (e) { console.log(videoContainer.value) }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    videoContainer.value.addEventListener('pointerdown', onPointerDown);
 | 
					    videoContainer.value.addEventListener('pointerdown', onPointerDown);
 | 
				
			||||||
@@ -218,6 +228,20 @@ onMounted(() => {
 | 
				
			|||||||
    opacity: 0.8;
 | 
					    opacity: 0.8;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.control-icon-disable {
 | 
				
			||||||
 | 
					    font-size: 1.2em;
 | 
				
			||||||
 | 
					    background-color: var(--text-inverse);
 | 
				
			||||||
 | 
					    color: var(--secondary);
 | 
				
			||||||
 | 
					    border-radius: 100%;
 | 
				
			||||||
 | 
					    width: 40px;
 | 
				
			||||||
 | 
					    height: 40px;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    align-items: center;
 | 
				
			||||||
 | 
					    justify-content: center;
 | 
				
			||||||
 | 
					    opacity: 0.8;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.video:hover .controls {
 | 
					.video:hover .controls {
 | 
				
			||||||
    opacity: 1;
 | 
					    opacity: 1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,6 @@
 | 
				
			|||||||
<template>
 | 
					<template>
 | 
				
			||||||
 <div class="default">
 | 
					 <div class="default">
 | 
				
			||||||
  <!-- <Carousel v-show="!loading" class="child"> -->
 | 
					 | 
				
			||||||
    <Changelog/>
 | 
					    <Changelog/>
 | 
				
			||||||
    <!-- <History/>
 | 
					 | 
				
			||||||
    <Advice/>
 | 
					 | 
				
			||||||
  </Carousel> -->
 | 
					 | 
				
			||||||
  <p v-show="loading" class="loading">
 | 
					  <p v-show="loading" class="loading">
 | 
				
			||||||
    <Icon icon="fa-spinner fa-solid" spin-pulse/> Chargement en cours
 | 
					    <Icon icon="fa-spinner fa-solid" spin-pulse/> Chargement en cours
 | 
				
			||||||
  </p>
 | 
					  </p>
 | 
				
			||||||
@@ -47,18 +43,13 @@ p {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.default  {
 | 
					.default  {
 | 
				
			||||||
    display: grid;
 | 
					    display: flex;
 | 
				
			||||||
    grid-template-rows: 1fr;
 | 
					 | 
				
			||||||
    grid-template-columns: 1fr;
 | 
					 | 
				
			||||||
    gap: 5px;
 | 
					    gap: 5px;
 | 
				
			||||||
    flex: 1;
 | 
					    flex: 1;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media screen and (max-width: 768px),
 | 
					@media screen and (max-width: 768px),
 | 
				
			||||||
       screen and (max-height: 607px) {
 | 
					       screen and (max-height: 607px) {
 | 
				
			||||||
    .default {
 | 
					 | 
				
			||||||
        grid-template-rows: 1fr;
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.child {
 | 
					.child {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
    <section class="changelog">
 | 
					    <section class="changelog">
 | 
				
			||||||
    <Welcome/>
 | 
					    <Welcome/>
 | 
				
			||||||
    <h2 class="changelog-title">📝 Changelog</h2>
 | 
					    <h2 class="changelog-title">📝 Changelog</h2>
 | 
				
			||||||
    <div class="changelog-overflow" v-if="changelog" >
 | 
					    <div v-if="changelog" class="changelog-overflow">
 | 
				
			||||||
        <div class="changelog-container" v-html="changelog" ></div>
 | 
					        <div class="changelog-container" v-html="changelog" ></div>
 | 
				
			||||||
    </div>
 | 
					    </div>
 | 
				
			||||||
    <div class="textSecond" v-else-if="!error"><Icon icon="fa-spinner fa-solid" spin-pulse/> Chargement en cours</div>
 | 
					    <div class="textSecond" v-else-if="!error"><Icon icon="fa-spinner fa-solid" spin-pulse/> Chargement en cours</div>
 | 
				
			||||||
@@ -39,6 +39,8 @@ function loadChangelog() {
 | 
				
			|||||||
            data = data.replaceAll("-*", "</span>");
 | 
					            data = data.replaceAll("-*", "</span>");
 | 
				
			||||||
            data = data.replaceAll("*_", "<span class='underline'>");
 | 
					            data = data.replaceAll("*_", "<span class='underline'>");
 | 
				
			||||||
            data = data.replaceAll("_*", "</span>");
 | 
					            data = data.replaceAll("_*", "</span>");
 | 
				
			||||||
 | 
					            data = data.replaceAll('/#', "<span class='changelog-tags'>");
 | 
				
			||||||
 | 
					            data = data.replaceAll('#/', "</span>");
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            changelog.value = data;
 | 
					            changelog.value = data;
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
@@ -102,12 +104,13 @@ function loadChangelog() {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.changelog-container {
 | 
					.changelog-container {
 | 
				
			||||||
    display: grid;
 | 
					    display: flex;
 | 
				
			||||||
    grid-template-columns: 1fr;
 | 
					    flex-direction: column;
 | 
				
			||||||
 | 
					    gap: 15px;
 | 
				
			||||||
 | 
					    overflow-y: auto;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
    width: 100%;
 | 
					    width: 100%;
 | 
				
			||||||
    grid-template-rows: auto;
 | 
					 | 
				
			||||||
    gap: 20px;
 | 
					 | 
				
			||||||
    
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.changelog {
 | 
					.changelog {
 | 
				
			||||||
@@ -119,7 +122,10 @@ function loadChangelog() {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
.changelog-overflow {
 | 
					.changelog-overflow {
 | 
				
			||||||
    overflow-y: auto;
 | 
					    overflow-y: auto;
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
    max-height: 100%;
 | 
					    max-height: 100%;
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.tags {
 | 
					.tags {
 | 
				
			||||||
@@ -225,20 +231,57 @@ function loadChangelog() {
 | 
				
			|||||||
    white-space: nowrap; /* Prevent line breaks */
 | 
					    white-space: nowrap; /* Prevent line breaks */
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@media screen and (max-width: 768px),
 | 
					.changelog-overflow {
 | 
				
			||||||
       screen and (max-height: 607px) {
 | 
					  position: relative;
 | 
				
			||||||
    .changelog-container {
 | 
					}
 | 
				
			||||||
        grid-template-columns: 1fr !important;
 | 
					
 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .changelog-container ul {
 | 
					    .changelog-container ul {
 | 
				
			||||||
        padding: 0
 | 
					     
 | 
				
			||||||
 | 
					        display: flex;
 | 
				
			||||||
 | 
					        flex-direction: column;
 | 
				
			||||||
 | 
					        gap: 10px;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .changelog-tags {
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    flex-direction: row;
 | 
				
			||||||
 | 
					    gap: 5px;
 | 
				
			||||||
 | 
					    background-color: var(--quaternary);
 | 
				
			||||||
 | 
					    padding: 5px;
 | 
				
			||||||
 | 
					    border-radius: 10px;
 | 
				
			||||||
 | 
					   }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@media screen and (max-width: 768px),
 | 
				
			||||||
 | 
					       screen and (max-height: 607px) {
 | 
				
			||||||
 | 
					    
 | 
				
			||||||
 | 
					        .changelog-container ul {
 | 
				
			||||||
 | 
					             padding: 0;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    .changelog-version ul li::before {
 | 
					    .changelog-version ul li::before {
 | 
				
			||||||
        display: none;
 | 
					        display: none;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    .welcome-container {
 | 
				
			||||||
 | 
					        flex-direction: column;
 | 
				
			||||||
 | 
					        align-items: center;
 | 
				
			||||||
 | 
					        gap: 10px;
 | 
				
			||||||
 | 
					        width: 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .welcome-actions {
 | 
				
			||||||
 | 
					        flex-direction: column;
 | 
				
			||||||
 | 
					        width: 100%;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    .changelog-tags {
 | 
				
			||||||
 | 
					         flex-direction: column;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
</style>
 | 
					</style>
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -126,6 +126,7 @@ const props = defineProps({
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
function openAuthorPage() {
 | 
					function openAuthorPage() {
 | 
				
			||||||
    if (!props.results.authorId) return;
 | 
					    if (!props.results.authorId) return;
 | 
				
			||||||
 | 
					    if(!props.results.author) return;
 | 
				
			||||||
    window.open(props.results.authorId, '_blank');
 | 
					    window.open(props.results.authorId, '_blank');
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -4,7 +4,7 @@
 | 
				
			|||||||
            <h2><Icon icon="fa-folder"/> Mes fichiers</h2>
 | 
					            <h2><Icon icon="fa-folder"/> Mes fichiers</h2>
 | 
				
			||||||
            <Box box-class="area-container" padding="close" level="second">
 | 
					            <Box box-class="area-container" padding="close" level="second">
 | 
				
			||||||
                <div class="upload-area">
 | 
					                <div class="upload-area">
 | 
				
			||||||
                    <Button :color-lower="status === 'download'" :disabled="status === 'download'" class="upload-button" @click="uploadFile()"><Icon icon="fa-upload"/> Ajouter un fichier</Button>
 | 
					                    <Button :color-lower="status === 'download'" :disabled="status === 'download'" class="upload-button" @click="uploadFile()"><Icon icon="fa-upload"/> Ajouter des fichiers</Button>
 | 
				
			||||||
                    <p v-if="status === 'download'" class="upload-file-name" ref="uploadStatus"><Icon icon='fa-spinner' spin-pulse/> Téléchargement en cours...</p>
 | 
					                    <p v-if="status === 'download'" class="upload-file-name" ref="uploadStatus"><Icon icon='fa-spinner' spin-pulse/> Téléchargement en cours...</p>
 | 
				
			||||||
                    <p v-else-if="status === 'error'" class="upload-status" ref="uploadStatus"><Error>Erreur lors du téléchargement</Error></p>
 | 
					                    <p v-else-if="status === 'error'" class="upload-status" ref="uploadStatus"><Error>Erreur lors du téléchargement</Error></p>
 | 
				
			||||||
                    <p v-else-if="status === 'toohigh'" class="upload-status" ref="uploadStatus"><Error>Le fichier est trop volumineux</Error></p>
 | 
					                    <p v-else-if="status === 'toohigh'" class="upload-status" ref="uploadStatus"><Error>Le fichier est trop volumineux</Error></p>
 | 
				
			||||||
@@ -14,15 +14,17 @@
 | 
				
			|||||||
                <p class="text-secondary infosup"><Icon icon="fa-circle-info"/> Ce système n'est pas un stockage permanent de données car il dépend du CDN de Discord. Vos fichiers peuvent exprirer à tout moment.</p>
 | 
					                <p class="text-secondary infosup"><Icon icon="fa-circle-info"/> Ce système n'est pas un stockage permanent de données car il dépend du CDN de Discord. Vos fichiers peuvent exprirer à tout moment.</p>
 | 
				
			||||||
            </Box>
 | 
					            </Box>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
        <div v-if="myFiles && myFiles.length > 0" class="uploaded-files">
 | 
					        <div  v-if="myFiles && myFiles.length > 0" class="uploaded-files-container">
 | 
				
			||||||
 | 
					        <div class="uploaded-files">
 | 
				
			||||||
            <span v-for="file in myFiles" :key="file.id"><VideoComposable  :video="file" delete/></span>
 | 
					            <span v-for="file in myFiles" :key="file.id"><VideoComposable  :video="file" delete/></span>
 | 
				
			||||||
        </div>
 | 
					        </div>
 | 
				
			||||||
 | 
					        </div>
 | 
				
			||||||
        <p v-else-if="isLoading" class="none"><Icon icon="fa-spinner" spin-pulse/> Chargement des fichiers...</p>
 | 
					        <p v-else-if="isLoading" class="none"><Icon icon="fa-spinner" spin-pulse/> Chargement des fichiers...</p>
 | 
				
			||||||
        <p v-else class="none"><Icon icon="fa-circle-xmark"/> Aucun fichier enregistré</p>
 | 
					        <p v-else class="none"><Icon icon="fa-circle-xmark"/> Aucun fichier enregistré</p>
 | 
				
			||||||
        <Modal icon="fa-upload" title="Uploader un fichier" ref="uploadModal">
 | 
					        <Modal icon="fa-upload" title="Uploader un fichier" ref="uploadModal">
 | 
				
			||||||
            <p>Etes-vous sûr de vouloir uploader ce fichier ?</p>
 | 
					            <p>Etes-vous sûr de vouloir uploader ces fichiers ?</p>
 | 
				
			||||||
            <p class="text-secondary">Ce fichier sera stocké sur le CDN de Discord et sera à jamais accessible. Ne diffusez rien de sensible.</p>
 | 
					            <p class="text-secondary">Ces fichiers seront stockés sur le CDN de Discord et seront à jamais accessibles. Ne diffusez rien de sensible.</p>
 | 
				
			||||||
            <p v-if="fileSelected" class="upload-modal-name"><Icon icon="fa-file"/> {{ fileSelected.name }}</p>
 | 
					            <p v-if="fileSelected.length > 0" v-for="value in fileSelected" class="upload-modal-name"><Icon icon="fa-file"/> {{ value.name }}</p>
 | 
				
			||||||
            <div class="upload-actions">
 | 
					            <div class="upload-actions">
 | 
				
			||||||
                <Button @click="closeModal()">Annuler</Button>
 | 
					                <Button @click="closeModal()">Annuler</Button>
 | 
				
			||||||
                <Button @click="confirmUpload()">Confirmer</Button>
 | 
					                <Button @click="confirmUpload()">Confirmer</Button>
 | 
				
			||||||
@@ -41,7 +43,7 @@ import { IORequest } from '@/utils/IORequest';
 | 
				
			|||||||
import { onMounted, onUnmounted, ref } from 'vue';
 | 
					import { onMounted, onUnmounted, ref } from 'vue';
 | 
				
			||||||
import Events from '@/utils/Events';
 | 
					import Events from '@/utils/Events';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const fileSelected = ref(null);
 | 
					const fileSelected = ref([]);
 | 
				
			||||||
const status = ref(false);
 | 
					const status = ref(false);
 | 
				
			||||||
const uploadModal = ref(null);
 | 
					const uploadModal = ref(null);
 | 
				
			||||||
const myFiles = ref([]);
 | 
					const myFiles = ref([]);
 | 
				
			||||||
@@ -66,53 +68,68 @@ function uploadFile() {
 | 
				
			|||||||
    const input = document.createElement('input');
 | 
					    const input = document.createElement('input');
 | 
				
			||||||
    input.type = 'file';
 | 
					    input.type = 'file';
 | 
				
			||||||
    input.accept = '.mp3,.wav,.ogg'; // Accept audio files
 | 
					    input.accept = '.mp3,.wav,.ogg'; // Accept audio files
 | 
				
			||||||
 | 
					    input.multiple = true;
 | 
				
			||||||
    input.onchange = (event) => {
 | 
					    input.onchange = (event) => {
 | 
				
			||||||
        const file = event.target.files[0];
 | 
					       const files = Array.from(event.target.files);
 | 
				
			||||||
        if (file) {
 | 
					       if (files.length > 0) {
 | 
				
			||||||
            fileSelected.value = file;
 | 
					            fileSelected.value = files;
 | 
				
			||||||
            // Here you would typically handle the file upload to the server
 | 
					            console.log(`Files selected:`, files.map(f => f.name));
 | 
				
			||||||
            console.log(`File selected: ${file.name}`);
 | 
					 | 
				
			||||||
            // Reset the input for future uploads
 | 
					 | 
				
			||||||
            input.value = '';
 | 
					            input.value = '';
 | 
				
			||||||
            // destroy input
 | 
					 | 
				
			||||||
            input.remove();
 | 
					            input.remove();
 | 
				
			||||||
            uploadModal.value.open();
 | 
					            uploadModal.value.open();
 | 
				
			||||||
        } else {
 | 
					        } else {
 | 
				
			||||||
            fileSelected.value = null;
 | 
					            fileSelected.value = [];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    input.click();
 | 
					    input.click();
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function confirmUpload() {
 | 
					async function confirmUpload() {
 | 
				
			||||||
    console.log(`Uploading file: ${fileSelected.value.name}`);
 | 
					    if (fileSelected.value.length === 0) return;
 | 
				
			||||||
    status.value = 'download';
 | 
					    status.value = 'download';
 | 
				
			||||||
    uploadModal.value.close();
 | 
					    uploadModal.value.close();
 | 
				
			||||||
    if(fileSelected.value) {
 | 
					
 | 
				
			||||||
        // Send the file to the server
 | 
					    let errorOccurred = false;
 | 
				
			||||||
        const reader = new FileReader();
 | 
					
 | 
				
			||||||
        reader.onload = () => {
 | 
					    for (const file of fileSelected.value) {
 | 
				
			||||||
            const fileBuffer = reader.result;
 | 
					        try {
 | 
				
			||||||
            // If it's higher than 300mb
 | 
					            const fileBuffer = await readFileAsArrayBuffer(file);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            if (fileBuffer.byteLength > 300 * 1024 * 1024) {
 | 
					            if (fileBuffer.byteLength > 300 * 1024 * 1024) {
 | 
				
			||||||
                status.value = 'toohigh';
 | 
					                status.value = 'toohigh';
 | 
				
			||||||
                console.error('File is too large');
 | 
					                errorOccurred = true;
 | 
				
			||||||
                return;
 | 
					                continue;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            await new Promise(resolve => {
 | 
				
			||||||
                IORequest('/UPLOAD/FILE', (response) => {
 | 
					                IORequest('/UPLOAD/FILE', (response) => {
 | 
				
			||||||
                if(!response) {
 | 
					                    if (!response || response === "TOOHIGH") {
 | 
				
			||||||
                    status.value = 'error';
 | 
					                        errorOccurred = true;
 | 
				
			||||||
                } else if(response === "TOOHIGH") {
 | 
					                        status.value = (response === "TOOHIGH") ? 'toohigh' : 'error';
 | 
				
			||||||
                    status.value = 'toohigh';
 | 
					 | 
				
			||||||
                } else {
 | 
					 | 
				
			||||||
                    status.value = 'success';
 | 
					 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					                    resolve();
 | 
				
			||||||
 | 
					                }, { name: file.name, file: fileBuffer });
 | 
				
			||||||
 | 
					            });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        } catch (err) {
 | 
				
			||||||
 | 
					            console.error("Erreur upload fichier:", file.name, err);
 | 
				
			||||||
 | 
					            errorOccurred = true;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    status.value = errorOccurred ? status.value : 'success';
 | 
				
			||||||
    refreshUploadedFiles();
 | 
					    refreshUploadedFiles();
 | 
				
			||||||
            }, {name: fileSelected.value.name, file: fileBuffer})
 | 
					    fileSelected.value = [];
 | 
				
			||||||
            fileSelected.value = null;
 | 
					}
 | 
				
			||||||
        };
 | 
					
 | 
				
			||||||
        reader.readAsArrayBuffer(fileSelected.value);
 | 
					// Petite fonction utilitaire pour transformer FileReader en promesse
 | 
				
			||||||
    }
 | 
					function readFileAsArrayBuffer(file) {
 | 
				
			||||||
 | 
					    return new Promise((resolve, reject) => {
 | 
				
			||||||
 | 
					        const reader = new FileReader();
 | 
				
			||||||
 | 
					        reader.onload = () => resolve(reader.result);
 | 
				
			||||||
 | 
					        reader.onerror = reject;
 | 
				
			||||||
 | 
					        reader.readAsArrayBuffer(file);
 | 
				
			||||||
 | 
					    });
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -149,6 +166,17 @@ function refreshUploadedFiles() {
 | 
				
			|||||||
    display: grid;
 | 
					    display: grid;
 | 
				
			||||||
    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
 | 
					    grid-template-columns: repeat(auto-fill, minmax(200px, 1fr));
 | 
				
			||||||
    gap: 10px;
 | 
					    gap: 10px;
 | 
				
			||||||
 | 
					    position: absolute;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					.uploaded-files-container {
 | 
				
			||||||
 | 
					    position: relative;
 | 
				
			||||||
 | 
					    flex: 1;
 | 
				
			||||||
 | 
					    display: flex;
 | 
				
			||||||
 | 
					    width: 100%;
 | 
				
			||||||
 | 
					    height: 100%;
 | 
				
			||||||
 | 
					    overflow-y: auto;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
.none {
 | 
					.none {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -12,6 +12,7 @@ import { IOListener, IORequest } from '@/utils/IORequest';
 | 
				
			|||||||
import { useUserStore } from '@/stores/userStore';
 | 
					import { useUserStore } from '@/stores/userStore';
 | 
				
			||||||
import { useGlobalStore } from '@/stores/globalStore';
 | 
					import { useGlobalStore } from '@/stores/globalStore';
 | 
				
			||||||
import events from '@/utils/Events.js';
 | 
					import events from '@/utils/Events.js';
 | 
				
			||||||
 | 
					import Events from '@/utils/Events.js';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    const router = useRouter();
 | 
					    const router = useRouter();
 | 
				
			||||||
    const interuptionMessage = ref(null);
 | 
					    const interuptionMessage = ref(null);
 | 
				
			||||||
@@ -43,6 +44,7 @@ import events from '@/utils/Events.js';
 | 
				
			|||||||
        IORequest("/GUILD/LIST", (response) => {
 | 
					        IORequest("/GUILD/LIST", (response) => {
 | 
				
			||||||
            if(response) {
 | 
					            if(response) {
 | 
				
			||||||
                userStore.userInfo.guilds = response;
 | 
					                userStore.userInfo.guilds = response;
 | 
				
			||||||
 | 
					                Events.emit("GUILD_LIST_UPDATE", response);
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user