Version 1.0.0 - Frontend

This commit is contained in:
2025-08-29 00:22:08 +02:00
parent b5dc2a9e37
commit 01b089f1f6
83 changed files with 5613 additions and 245 deletions

View File

@@ -10,7 +10,13 @@ export default {
},
off(eventName, fn) {
throw {message:'Not implemented'}
if(Events.has(eventName)) {
const listeners = Events.get(eventName)
const index = listeners.indexOf(fn)
if(index !== -1) {
listeners.splice(index, 1)
}
}
},
emit(eventName, data) {
if(Events.has(eventName)) {

View File

@@ -1,5 +1,6 @@
<script setup>
import DefaultSplash from '@/components/UI/DefaultSplash.vue';
import MusicAnimation from '@/components/UI/MusicAnimation.vue';
const defaultMessage = "On s'accorde et on prépare le concert !";
const connectMsg = "Erreur de connexion au serveur : xhr poll error"
@@ -14,8 +15,8 @@ const props = defineProps({
</script>
<template>
<DefaultSplash>
<h1 v-if="!interuptionMessage" class="separate"><Icon spin-pulse icon="fa-solid fa-spinner"/> Chargement de l'interface</h1>
<DefaultSplash gap="0">
<h1 v-if="!interuptionMessage" class="separate"> Chargement de l'interface</h1>
<h1 v-else-if="interuptionMessage == connectMsg"><Icon icon="fa-solid fa-circle-exclamation"/> Echec de connexion</h1>
<h1 v-else><Icon icon="fa-solid fa-warning"/> Connexion interrompue</h1>
<div class="separate-col">
@@ -24,6 +25,7 @@ const props = defineProps({
</div>
<p v-if="interuptionMessage" class="error"><Icon icon="fa-solid fa-circle-xmark"/> {{ interuptionMessage }}</p>
<p v-else>{{ defaultMessage }}</p>
<MusicAnimation />
</DefaultSplash>
</template>
<style scoped>
@@ -60,4 +62,11 @@ const props = defineProps({
font-size: 0.8em;
color: var(--text-secondary);
}
@media screen and (max-width: 768px),
screen and (max-height: 607px) {
h1 {
font-size: 6vw;
}
}
</style>

103
src/utils/Logic.js Normal file
View File

@@ -0,0 +1,103 @@
import Events from "@/utils/Events";
import { IORequest, IOListener } from "@/utils/IORequest";
import { useGlobalStore } from "@/stores/globalStore";
import { useUserStore } from "@/stores/userStore";
export function loadLogic() {
const globalStore = useGlobalStore();
Events.on("playlist:delete", (playlist) => {
IORequest("/PLAYLISTS/DELETE", () => {
Events.emit("VIEW_RESET")
Events.emit("playlistComponent:update")
refreshPlaylist()
}, playlist.playlistId);
});
Events.on("video:add", (video) => {
IORequest("/PLAYLISTS/ADD_SONG", (response) => {
if(response) {
refreshPlaylist()
openPlaylist(response);
} else {
console.error("Failed to add video");
}
}, { id: video.playlistId, song: video.video });
});
Events.on("playlist:refresh", (playlist) => {
IORequest("/PLAYLISTS/REFRESH", async (data) => {
Events.emit("playlist:hasRefresh");
refreshPlaylist()
if(!data) return
await openPlaylist(data, true);
}, playlist.playlistId)
})
Events.on("playlist:rename", (data) => {
IORequest("/PLAYLISTS/RENAME", async (response) => {
if(response) {
refreshPlaylist()
openPlaylist(response);
} else {
console.error("Failed to rename playlist");
}
}, { id: data.id, newName: data.newName });
});
Events.on("video:delete", (video) => {
if(!globalStore.actualPlaylistId) return;
IORequest("/PLAYLISTS/REMOVE_SONG", (response) => {
if(response) {
refreshPlaylist()
openPlaylist(response);
} else {
console.error("Failed to delete video");
}
}, { id: globalStore.actualPlaylistId, songId: video.video.id });
});
Events.on("view:change", (component) => {
if(component.__name === "PlaylistView") return;
if(component.__name === "LoadingView") return;
globalStore.actualPlaylistId = null;
});
Events.on("playlist:open", openPlaylist);
Events.on("logic:init", refreshPlaylist);
}
export function refreshPlaylist() {
const userStore = useUserStore();
IORequest("/PLAYLISTS/LIST", (data) => {
userStore.playlists = data;
Events.emit("playlist:init", data);
})
}
export function openPlaylist(playlist, hasBeenActualized) {
const globalStore = useGlobalStore();
Events.emit("VIEW_PLAYLIST", {playlist, hasBeenActualized});
globalStore.actualPlaylistId = playlist.playlistId;
console.log("Opening playlist:", playlist.title, "with ID:", playlist.playlistId);
}
export function updateChannel() {
const globalStore = useGlobalStore();
globalStore.currentChannel = null;
IORequest("/CHANNEL", (data) => {
if(data) {
console.log(globalStore.actualServer)
console.log(data.guildId)
if(data.guildId === globalStore.actualServer.id) {
globalStore.currentChannel = data;
}
if(globalStore.currentChannel.id === globalStore.actualServer.id) {
globalStore.currentChannel = null;
}
} else {
globalStore.currentChannel = null;
}
})
}

View File

@@ -39,6 +39,14 @@ import events from '@/utils/Events.js';
});
});
IOListener("/GUILD/UPDATE", () => {
IORequest("/GUILD/LIST", (response) => {
if(response) {
userStore.userInfo.guilds = response;
}
})
})
IOListener("AUTH_ERROR", (error) => {
console.error("Authentication error:", error);
loginStore.setToken(null);
@@ -50,21 +58,25 @@ import events from '@/utils/Events.js';
socket.on("connect", () => {
interuptionMessage.value = null;
globalStore.actualPlaylistId = null;
globalStore.setLoading(true);
});
socket.on("connect_error", (error) => {
interuptionMessage.value = "Erreur de connexion au serveur : " + error.message;
globalStore.actualPlaylistId = null;
tryReconnect();
});
socket.on("error", () => {
interuptionMessage.value = "Erreur de connexion au serveur, veuillez réessayer plus tard";
globalStore.actualPlaylistId = null;
tryReconnect();
})
socket.on("disconnect", () => {
interuptionMessage.value = "Déconnecté du serveur";
globalStore.actualPlaylistId = null;
tryReconnect();
})

View File

@@ -29,6 +29,40 @@ export function getReadableDuration(duration) {
return max
}
// Get hh:mm:ss format
export function getVideoDuration(duration) {
var max = ""
duration *= 1000;
const maxhours = Math.floor(duration / 3600000);
var maxmin = Math.trunc(duration / 60000) - (Math.floor(duration / 60000 / 60) * 60);
var maxsec = Math.floor(duration / 1000) - (Math.floor(duration / 1000 / 60) * 60);
if (maxsec < 10) {
maxsec = `0${maxsec}`;
}
if(maxhours != 0) {
if (maxmin < 10) {
maxmin = `0${maxmin}`;
}
max = maxhours + ":" + maxmin + ":" + maxsec
} else {
max = maxmin + ":" + maxsec
}
return max
}
export function getSecondsDuration(duration) {
// Duration is in format hh:mm:ss and can be just m:ss or mm:ss
var durationArray = duration.split(":");
@@ -41,4 +75,5 @@ export function getSecondsDuration(duration) {
seconds = parseInt(durationArray[0]);
}
return seconds;
}
}