This commit is contained in:
2025-03-13 22:08:06 +01:00
commit bab5571428
93 changed files with 4323 additions and 0 deletions

24
app/frontend/.gitignore vendored Normal file
View File

@@ -0,0 +1,24 @@
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?

View File

@@ -0,0 +1,8 @@
{
"compilerOptions": {
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
}
}
}

30
app/frontend/package.json Normal file
View File

@@ -0,0 +1,30 @@
{
"name": "frontend",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
},
"devDependencies": {
"@mdi/font": "^7.4.47",
"@vitejs/plugin-vue": "^5.2.1",
"autoprefixer": "^10.4.20",
"postcss": "^8.5.2",
"postcss-import": "^16.1.0",
"postcss-simple-vars": "^7.0.1",
"video.js": "^8.21.0",
"vite": "^6.1.0"
},
"dependencies": {
"events": "^3.3.0",
"filesize": "^10.1.6",
"js-cookie": "^3.0.5",
"moment": "^2.30.1",
"vite-plugin-vuetify": "^2.1.0",
"vue": "^3.5.13",
"vuetify": "^3.7.12"
}
}

View File

@@ -0,0 +1,7 @@
export default {
plugins: {
'postcss-import': {},
'postcss-simple-vars': {},
'autoprefixer': {}
}
}

View File

@@ -0,0 +1,7 @@
import 'vite/modulepreload-polyfill'
import App from '@/components/auth/App.vue';
import("@/plugins/vue_loader.js").then(utils => {
utils.createVue(App, "#app");
})

View File

@@ -0,0 +1,8 @@
// add the beginning of your app entry
import 'vite/modulepreload-polyfill'
import App from '../components/torrent/App.vue';
import("@/plugins/vue_loader.js").then(utils => {
utils.createVue(App, "#app");
})

View File

@@ -0,0 +1,49 @@
<template>
<Base>
<v-card class="elevation-12">
<v-toolbar color="primary" dark :flat="true">
<v-toolbar-title>Login form</v-toolbar-title>
<v-spacer/>
</v-toolbar>
<v-card-text class="red--text">
{{error_message}}
</v-card-text>
<v-card-text>
<!-- <v-form @submit.prevent="checkForm" id="check-login-form">-->
<v-form id="check-login-form" method="post" action="/user/login/">
<input type="hidden" :value="Cookies.get('csrftoken')" name="csrfmiddlewaretoken">
<v-text-field id="username" v-model="username" label="Username" name="username" prepend-icon="mdi-account" type="text"/>
<v-text-field id="password" v-model="password" label="Password" name="password" prepend-icon="mdi-lock" type="password"/>
</v-form>
</v-card-text>
<v-card-actions>
<v-btn color="warning" href="/password_reset/" target="_blank" variant="plain">Password lost</v-btn>
<v-spacer/>
<v-btn type="submit" color="primary" form="check-login-form" variant="elevated" class="text-overline">Login</v-btn>
</v-card-actions>
</v-card>
</Base>
</template>
<script setup>
import Cookies from "js-cookie";
import Base from "./Base.vue";
</script>
<script>
export default {
data(){
return {
error_message: "",
username: "",
password: ""
}
},
mounted() {
if(form_error){
this.error_message = "Bad login/password";
console.log(JSON.stringify(form_error));
}
}
}
</script>

View File

@@ -0,0 +1,13 @@
<template>
<v-app id="inspire">
<v-main>
<v-container class="fill-height" :fluid="true">
<v-row align="center" justify="center">
<v-col cols="12" sm="8" md="4">
<slot></slot>
</v-col>
</v-row>
</v-container>
</v-main>
</v-app>
</template>

View File

@@ -0,0 +1,66 @@
<template>
<v-list>
<v-list-item>
<v-list-item-action class="justify-center">
<FriendManager :friends="friends" @friends-updated="fetchFriends"/>
</v-list-item-action>
</v-list-item>
<v-divider/>
<v-list-item
:active="active_user === default_user_id"
@click="$emit('userSelected')"
>
<template v-slot:title>
My torrents
</template>
</v-list-item>
<v-list-item
v-for="(friend, i) in friends"
:key="i"
:active="active_user === friend.id"
@click="$emit('userSelected', friend)"
>
<template v-slot:title>
{{friend.username}}
</template>
<template v-slot:subtitle>
{{friend.count_torrent}} torrent{{friend.count_torrent !== 1 ? 's':''}}
</template>
</v-list-item>
</v-list>
</template>
<script setup>
import FriendManager from "./FriendManager.vue";
</script>
<script>
export default {
emits: ["userSelected"],
props: {
active_user: {
type: Number,
required: false
}
},
data(){
return {
friends: [],
default_user_id: current_user.id
}
},
async mounted(){
await this.fetchFriends();
},
methods: {
async fetchFriends(){
let filters = {
"only_friends": true
}
let response = await fetch(`/api/users/?${new URLSearchParams(filters)}`);
this.friends = await response.json();
},
}
}
</script>

View File

@@ -0,0 +1,132 @@
<template>
<v-card>
<v-card-title class="text-center">Manage friends</v-card-title>
<v-card-text
v-if="add_status"
class="text-center justify-center"
:style="{
'background-color': add_status.success ? 'green': 'red',
'padding-top': '13px'
}"
v-text="add_status.message"
/>
<v-card-actions class="justify-center">
<v-text-field @keyup.enter="addFriendRequest" v-model="username_model" prepend-icon="mdi-account-plus"/>
</v-card-actions>
<v-card v-if="friend_requests.length">
<v-card-title>Friends requests</v-card-title>
<v-list>
<v-list-item
v-for="(fr, i) in friend_requests"
:key="i"
:title="fr.username"
>
<template v-slot:append>
<v-row>
<v-col>
<v-btn icon="mdi-check" color="green" @click="acceptFriendRequest(i)"/>
</v-col>
<v-col>
<v-btn icon="mdi-cancel" color="red" @click="removeFriendRequest(i)"/>
</v-col>
</v-row>
</template>
</v-list-item>
</v-list>
</v-card>
<v-divider/>
<v-card v-if="friends.length">
<v-card-title>Friends</v-card-title>
<v-list>
<v-list-item
v-for="(user, i) in friends"
:key="i"
prepend-icon="mdi-account"
:title="user.username"
>
<template v-slot:append>
<v-btn icon="mdi-minus" color="red" variant="plain" @click="removeFriend(i)"/>
</template>
</v-list-item>
</v-list>
</v-card>
</v-card>
</template>
<script>
import Cookies from "js-cookie";
let initial_add_status = {
message: "",
success: null
}
export default {
emits: ["friendsUpdated"],
props: {
friends: {
type: Array,
required: true
}
},
data(){
return {
enabled: false,
username_model: "",
friend_requests: [],
add_status: null
}
},
mounted() {
this.fetchFriendRequests();
},
methods: {
// friend request related
async fetchFriendRequests(){
let response = await fetch("/api/friend_requests/");
this.friend_requests = await response.json()
},
async addFriendRequest(username=null){
if(username === null || typeof username !== "string"){
username = this.username_model
}
let response = await fetch(`/api/users/${username}/add_friend_request/`);
this.add_status = await response.json();
setTimeout(() => {
this.add_status = null;
}, 3000)
this.username_model = "";
await this.fetchFriendRequests();
this.$emit("friendsUpdated");
},
async acceptFriendRequest(i){
let friend_request = this.friend_requests[i];
await this.addFriendRequest(friend_request.username);
this.friend_requests.splice(i, 1);
this.$emit("friendsUpdated");
},
async removeFriendRequest(i){
let friend_request = this.friend_requests[i];
let response = await fetch(`/api/friend_requests/${friend_request.id}/`,
{
method: "DELETE",
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
},
}
);
if(response.ok) this.friend_requests.splice(i, 1);
// todo : check success
},
//friends related
async removeFriend(i){
let user = this.friends[i];
let response = await fetch(`/api/users/${user.id}/remove_friend/`);
let json = await response.json();
if(json.success) this.friends.splice(i, 1);
this.$emit("friendsUpdated");
},
}
}
</script>

View File

@@ -0,0 +1,32 @@
<template>
<v-dialog v-model="enabled" max-width="500">
<template v-slot:activator="{props}">
<v-btn color="blue" prepend-icon="mdi-account-group" text="Manage friends" v-bind="props"/>
</template>
<FriendForm :friends="friends" @friends-updated="$emit('friendsUpdated')"/>
</v-dialog>
</template>
<script setup>
import FriendForm from "./FriendForm.vue";
</script>
<script>
export default {
emits: ["friendsUpdated"],
props: {
friends: {
type: Array,
required: true
}
},
data(){
return {
enabled: false
}
},
methods: {
}
}
</script>

View File

@@ -0,0 +1,175 @@
<template>
<v-app>
<v-navigation-drawer :permanent="true">
<v-list>
<v-list-item>
<v-list-item-action class="justify-center">
<v-row>
<v-col class="text-center">
<UploadForm @torrent_added="torrentAdded"/>
</v-col>
</v-row>
</v-list-item-action>
</v-list-item>
<v-divider/>
</v-list>
</v-navigation-drawer>
<v-navigation-drawer v-model="right_drawer" location="right" temporary>
<Friend v-if="right_drawer" :active_user="display_user.id" @userSelected="userSelectedUpdated"/>
</v-navigation-drawer>
<v-app-bar>
<v-app-bar-title><v-btn variant="plain" href="/">Oxpanel</v-btn></v-app-bar-title>
<v-spacer/>
<v-menu>
<template v-slot:activator="{ props }">
<v-btn v-bind="props">Manage</v-btn>
</template>
<v-list>
<v-list-item href="/password_change/" title="Change password"/>
<v-list-item>
<v-list-item-action>
<form action="/logout/" method="post">
<input type="hidden" name="csrfmiddlewaretoken" :value="Cookies.get('csrftoken')">
<button>Disconnect</button>
</form>
</v-list-item-action>
</v-list-item>
</v-list>
</v-menu>
<v-btn
@click="right_drawer = !right_drawer"
prepend-icon="mdi-account-group"
:color="display_user.id === user.id ? 'green':'orange'"
:text="display_user.username"
/>
</v-app-bar>
<v-main>
<TorrentList :loading="loading_torrents" :torrents="torrents" :delete_disabled="user.id !== display_user.id"/>
</v-main>
</v-app>
</template>
<script setup>
import Cookies from "js-cookie";
import TorrentList from "@/components/torrent/TorrentList.vue";
import UploadForm from "@/components/torrent/UploadForm.vue";
import Friend from "@/components/auth/Friend.vue";
</script>
<script>
export default {
data(){
return {
right_drawer: false,
user: current_user,
display_user: {
id: current_user.id,
username: "My torrents"
},
loading_torrents: false,
filters: {},
torrents: []
}
},
async mounted(){
this.$ws.connect("/ws/torrent_event/");
this.$ws.on("connect", () => {
this.$ws.send(JSON.stringify({"context": "change_follow_user", "user_id": this.display_user.id}));
});
this.$ws.on("json_message", (message) => {
switch(message.context){
case "transmission_data_updated":
this.updateTransmissionData(message.data);
break;
case "add_torrent":
this.fetchTorrent(message.torrent_id);
break;
case "remove_torrent":
this.removeTorrent(message.torrent_id);
break;
case "update_torrent":
this.updateTorrent(message.torrent_id, message.updated_fields)
}
})
await this.fetchTorrents();
},
methods: {
torrentAdded(torrent){
if(!(torrent.id in this.torrentsAsObject)){
this.torrents.unshift(torrent);
}
},
changeDisplayUser(user){
if(user){
this.display_user = {
"username": this.user.id === user.id ? "My torrents": `${user.username} torrents`,
"id": user.id
}
}else{
}
this.display_user = {
"username": this.user.id === user.id ? "My torrents": `${user.username} torrents`,
"id": user.id
}
this.$ws.send(JSON.stringify({"context": "change_follow_user", "user_id": this.display_user.id}));
},
updateTransmissionData(data){
if(data.hashString in this.torrentsAsObject){
this.torrentsAsObject[data.hashString].transmission_data = data
}
},
async fetchTorrents(){
this.loading_torrents = true;
let filters = {...this.filters, user: this.display_user.id},
url = `/api/torrents/?${new URLSearchParams(filters)}`;
let response = await fetch(url);
this.torrents = await response.json();
this.loading_torrents = false;
},
async fetchTorrent(torrent_id){
if(torrent_id in this.torrentsAsObject) return;
let url = `/api/torrents/${torrent_id}/`;
let response = await fetch(url);
if(response.ok){
let torrent = await response.json();
if(!(torrent.id in this.torrentsAsObject)) this.torrents.unshift(torrent);
}else{
setTimeout(() => this.fetchTorrent(torrent_id), 1000);
}
},
async updateTorrent(torrent_id, updated_fields){
if(torrent_id in this.torrentsAsObject){
for(let key in updated_fields){
this.torrentsAsObject[torrent_id][key] = updated_fields[key];
}
}
},
async removeTorrent(torrent_id){
if(!(torrent_id in this.torrentsAsObject)) return;
for(let i = 0; i < this.torrents.length; i++){
if(this.torrents[i].id === torrent_id){
this.torrents.splice(i, 1);
break;
}
}
},
async userSelectedUpdated(user){
await this.changeDisplayUser(user ? user: this.user);
await this.fetchTorrents();
this.right_drawer = false
},
},
computed: {
torrentsAsObject(){
let r = {};
this.torrents.forEach(torrent => {
r[torrent.id] = torrent;
});
return r;
}
}
}
</script>

View File

@@ -0,0 +1,54 @@
<template>
<v-list-item
style="background-color: #434343"
@click.stop="downloadClicked"
:title="file.rel_name"
:subtitle="fs_format(file.size)"
>
<template v-slot:prepend>
<v-btn @click.stop="downloadClicked" :disabled="!is_download_finished" icon="mdi-download" color="green" variant="text"/>
<v-dialog v-if="file.is_stream_video" v-model="video_modal" width="75%" height="100%">
<template v-slot:activator="{ props }">
<v-btn v-bind="props" icon="mdi-play" variant="text"/>
</template>
<v-card>
<VideoPlayer class="text-center"/>
</v-card>
</v-dialog>
</template>
</v-list-item>
</template>
<script setup>
import {fs_format} from "@/plugins/utils.js";
import VideoPlayer from "@/components/utils/VideoPlayer.vue";
</script>
<script>
export default {
props: {
file: {
required: true,
type: Object,
},
is_download_finished: {
required: true,
type: Boolean,
}
},
data(){
return {
video_modal: false,
}
},
methods: {
downloadClicked(){
if(!this.is_download_finished) return;
let a = document.createElement("a");
a.href = this.file.download_url;
a.setAttribute("download", "download");
a.click();
}
}
}
</script>

View File

@@ -0,0 +1,48 @@
<template>
<v-list density="compact">
<div v-if="loading">
<v-progress-circular indeterminate/>
Loading files ...
</div>
<FileItem v-for="file in files" :key="file.id" :file="file" :is_download_finished="is_download_finished"/>
</v-list>
</template>
<script setup>
import FileItem from "@/components/torrent/FileItem.vue";
</script>
<script>
export default {
props: {
torrent_id: {
required: true,
type: String,
},
is_download_finished: {
required: true,
type: Boolean,
}
},
data(){
return {
loading: true,
files: [],
filters: {
torrent: this.torrent_id,
}
}
},
async mounted(){
await this.fetchFiles();
},
methods: {
async fetchFiles(){
this.loading = true;
let response = await fetch(`/api/torrent/files?${new URLSearchParams(this.filters)}`);
this.files = await response.json();
this.loading = false;
}
}
}
</script>

View File

@@ -0,0 +1,126 @@
<template>
<v-card @click="show_files = !show_files">
<v-progress-linear height="20" :color="progressData.color" :model-value="progressData.value">
<!-- barre de progression -->
<v-progress-circular
v-if="!torrent.transmission_data.rateDownload && !torrent.transmission_data.rateUpload"
size="15"
indeterminate
:color="torrent.transmission_data.progress < 100 ? 'green':'red'"
/>
<v-icon
v-else
:color="torrent.transmission_data.rateDownload ? 'green':'red'"
:icon="torrent.transmission_data.rateDownload ? 'mdi-arrow-down-bold':'mdi-arrow-up-bold'"
/>
<strong style="padding-left: 5px">
{{progressData.value}}%
<strong
v-if="torrent.transmission_data.rateDownload || torrent.transmission_data.rateUpload"
>
({{torrent.transmission_data.rateDownload ? fs_speed_format(torrent.transmission_data.rateDownload):fs_speed_format(torrent.transmission_data.rateUpload)}}/s)
</strong>
</strong>
</v-progress-linear>
<v-row no-gutters>
<!-- ligne du haut -->
<v-col>
<v-card-text v-text="torrent.name"></v-card-text>
</v-col>
<v-col lg="1">
<v-card-text v-text="fs_format(torrent.size)"></v-card-text>
</v-col>
</v-row>
<v-row v-if="torrent.transmission_data.progress < 100" justify="end" no-gutters>
<!-- ligne du milieu -->
<v-col lg="2">
<v-card-text>remaining : {{fs_format(torrent.transmission_data.leftUntilDone)}}/{{progressData.eta}}</v-card-text>
</v-col>
</v-row>
<v-card-actions>
<v-btn :disabled="torrent.transmission_data.progress < 100" @click.stop="downloadClicked" color="green" :icon="torrent.count_files === 1 ? 'mdi-download':'mdi-folder-download'"/>
<v-dialog v-model="share_modal" max-width="600">
<template v-slot:activator="{props}">
<v-btn icon="mdi-share-variant" v-bind="props"/>
</template>
<TorrentShare :torrent="torrent"/>
</v-dialog>
<v-spacer/>
<v-btn @click.stop="deleteClicked" color="red" icon="mdi-delete-variant" :disabled="delete_disabled"/>
</v-card-actions>
<v-expand-transition>
<div v-if="show_files">
<v-divider />
<FileList v-if="show_files" :torrent_id="torrent.id" :is_download_finished="torrent.transmission_data.progress >= 100"/>
</div>
</v-expand-transition>
</v-card>
</template>
<script setup>
import {fs_format, fs_speed_format} from "@/plugins/utils.js";
import FileList from "@/components/torrent/FileList.vue";
import TorrentShare from "@/components/torrent/TorrentShare.vue";
</script>
<script>
import Cookies from "js-cookie";
import {toHHMMSS} from "@/plugins/utils.js";
export default {
emits: ["delete"],
props: {
torrent: {
required: true,
type: Object,
},
delete_disabled: {
required: true,
type: Boolean,
}
},
data(){
return {
show_files: false,
share_modal: false,
}
},
methods: {
async downloadClicked(){
if(this.torrent.transmission_data.progress < 100) return;
let a = document.createElement("a");
a.href = this.torrent.download_url;
a.setAttribute("download", "download");
a.click();
},
async deleteClicked(){
this.$emit("delete", this.torrent.id);
await fetch(`/api/torrents/${this.torrent.id}/`, {
method: "DELETE",
headers: {
"X-CSRFToken": Cookies.get("csrftoken"),
}
})
}
},
computed: {
progressData(){
let color = "red", value = 0, eta;
if(this.torrent.transmission_data.progress < 100){
color = "blue";
value = this.torrent.transmission_data.progress;
if(this.torrent.transmission_data.eta !== -1){
eta = toHHMMSS(this.torrent.transmission_data.eta);
}else{
eta = "-";
}
}else{
color = "green";
value = Number((this.torrent.transmission_data.uploadRatio / 5) * 100).toFixed(2)
if(value > 100) value = 100;
}
return {color, value, eta};
}
}
}
</script>

View File

@@ -0,0 +1,45 @@
<template>
<v-container fluid>
<TorrentItem
v-if="torrents.length"
v-for="(torrent, i) in torrents"
:key="torrent.id"
:torrent="torrent"
:delete_disabled="delete_disabled"
@delete="torrents.splice(i, 1)"
/>
<v-card v-else :color="loading ? 'orange':'red'">
<v-card-text v-if="loading" class="text-center">loading torrents...</v-card-text>
<v-card-text v-else class="text-center">There is no torrent to display</v-card-text>
</v-card>
</v-container>
</template>
<script setup>
import TorrentItem from "./TorrentItem.vue";
</script>
<script>
export default {
props: {
torrents: {
required: true,
type: Array
},
loading: {
required: true,
type: Boolean
},
delete_disabled: {
required: true,
type: Boolean,
}
},
methods: {
deleteClicked(i){
console.log("delete clicked !", i)
this.torrents.splice(i, 1)
}
}
}
</script>

View File

@@ -0,0 +1,110 @@
<template>
<v-container>
<v-card>
<v-card-title>Sharing of `{{ torrent.name }}`</v-card-title>
<v-divider/>
<v-row>
<v-col>
<v-card class="justify-center">
<v-card-title>Share with others users</v-card-title>
<v-card-text
v-if="message"
class="text-center justify-center"
style="background-color: green; padding-top: 13px"
v-text="message"
/>
<v-card-text>
<v-autocomplete
v-model="share_input"
:items="filteredUser"
item-title="username"
item-value="id"
/>
</v-card-text>
</v-card>
</v-col>
<v-divider :vertical="true"/>
<!-- <v-col>-->
<!-- <v-card-text>(public share W.I.P., only enabled to trusted User)</v-card-text>-->
<!-- </v-col>-->
</v-row>
</v-card>
</v-container>
</template>
<script>
import Cookies from "js-cookie";
export default {
props: {
torrent: {
required: true,
type: Object,
}
},
data(){
return {
users: [],
share_input: "",
message: ""
}
},
watch: {
share_input(newValue, oldValue){
if(newValue){
this.sharedFieldChange(newValue);
}
}
},
async mounted(){
await this.fetchUsers();
},
methods: {
async sharedFieldChange(user_id){
let username;
for(let user of this.users){
if(user_id === user.id){
username = user.username;
break;
}
}
let form = new FormData();
form.append("user_id", user_id);
let response = await fetch(`/api/torrents/${this.torrent.id}/share/`, {
method: "POST",
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
},
body: form
})
let status = await response.json();
if(status.success){
this.share_message_status = `Shared with '${username}' successfully`
setTimeout(() => {
this.share_message_status = ""
}, 3000);
this.torrent.shared_users.push(user_id)
}
this.$nextTick(() => {
this.share_input = "";
})
},
async fetchUsers(){
let response = await fetch("/api/users/");
this.users = await response.json();
}
},
computed: {
filteredUser(){
let r = [];
this.users.forEach(user => {
if(this.torrent.user !== user.id && user.id !== current_user.id && !(this.torrent.shared_users.includes(user.id))){
r.push(user)
}
})
return r
}
}
}
</script>

View File

@@ -0,0 +1,105 @@
<template>
<v-dialog v-model="enabled" max-width="500">
<template v-slot:activator="{props}">
<v-btn color="blue" prepend-icon="mdi-file-upload" text=".torrent" v-bind="props"/>
</template>
<input type="file" multiple="multiple" ref="fileinput" @change="uploadFieldChange" hidden="hidden" accept=".torrent">
<v-card>
<v-card-title class="text-center">Send Torrent Files</v-card-title>
<v-card-actions class="justify-center">
<v-btn @click="uploadFieldTriggered" color="blue" prepend-icon="mdi-plus" variant="tonal" text="add .torrent" />
<v-btn :disabled="!attachments.length" color="green" variant="tonal" icon="mdi-check" @click="sendFiles"/>
<v-btn @click="attachments.splice(0, attachments.length)" :disabled="!attachments.length" color="red" variant="tonal" icon="mdi-cancel"/>
</v-card-actions>
<v-list >
<v-list-item
v-for="(attachment, i) in attachments"
:key="i"
@click="this.attachments.splice(i, 1)"
prepend-icon="mdi-file"
:title="attachment.file_object.name"
>
<v-list-item-subtitle :class="`text-${attachment.text_color}`" v-text="attachment.response ? attachment.response.message:'waiting'"/>
</v-list-item>
</v-list>
</v-card>
</v-dialog>
</template>
<script>
import Cookies from "js-cookie";
export default {
emits: ["torrent_added"],
data(){
return {
enabled: false,
attachments: []
}
},
watch: {
enabled(newValue, oldValue){
if(newValue){
this.$nextTick(() => {
this.uploadFieldTriggered();
})
}else{
this.attachments.splice(0, this.attachments.length)
}
},
// attachments(newValue, oldValue){
// this.status.pop()
// }
},
methods: {
async sendFiles(){
let form, response, data;
for (const attachment of this.attachments) {
if(!attachment.response){
form = new FormData();
form.append("file", attachment.file_object);
// form.append("csrfmiddlewaretoken", Cookies.get('csrftoken'))
response = await fetch("/api/torrents/", {
method: "POST",
headers: {
"X-CSRFToken": Cookies.get('csrftoken')
},
body: form
})
data = await response.json()
attachment.response = data
switch (data.status){
case "error":
attachment.text_color = "red";
break;
case "warn":
attachment.text_color = "yellow";
this.$emit("torrent_added", data.torrent);
break;
case "success":
attachment.text_color = "green"
this.$emit("torrent_added", data.torrent);
break;
}
}
}
},
uploadFieldChange(event){
let files = event.target.files || event.dataTransfer.files;
if(files.length){
Array.prototype.forEach.call(files, file => {
this.attachments.push({
file_object: file,
response: null,
text_color: "blue"
})
})
}
},
uploadFieldTriggered(){
this.$refs.fileinput.click();
}
}
}
</script>

View File

@@ -0,0 +1,41 @@
<template>
<div>
<video ref="videoPlayer" id="my-video" controls preload="auto" class="video-js vjs-default-skin vjs-16-9"></video>
</div>
</template>
<script>
import "video.js/dist/video-js.min.css";
import videojs from "video.js";
export default {
name: "VideoPlayer",
props: {
options: {
type: Object,
default(){
return {};
}
}
},
data(){
return {
player: null,
}
},
mounted() {
this.player = videojs(this.$refs.videoPlayer, this.options, () => {
this.player.log("onPlayerReady", this);
})
},
beforeUnmount() {
if(this.player) {
this.player.dispose();
}
}
}
</script>
<style scoped>
</style>

View File

@@ -0,0 +1,17 @@
import {filesize} from "filesize";
function fs_format(value){
return filesize(value, {round: 2, exponent: 3})
}
function fs_speed_format(value){
return filesize(value, {})
}
function toHHMMSS(time) {
let sec_num = parseInt(time), hours = Math.floor(sec_num / 3600), minutes = Math.floor(sec_num / 60) % 60, seconds = sec_num % 60;
return [hours, minutes, seconds]
.map(v => v < 10 ? "0" + v : v).filter((v, i) => v !== "00" || i > 0).join(":");
}
export {fs_format, fs_speed_format, toHHMMSS}

View File

@@ -0,0 +1,7 @@
import { createApp } from 'vue';
import Vuetify from "./vuetify"
import Ws from "./ws";
export function createVue(component, dom_id){
return createApp(component).use(Vuetify).use(Ws).mount(dom_id)
}

View File

@@ -0,0 +1,30 @@
import '@mdi/font/css/materialdesignicons.css' // Ensure you are using css-loader
import 'vuetify/styles'
import { createVuetify } from 'vuetify'
import colors from 'vuetify/lib/util/colors.mjs'
// import { aliases, mdi } from 'vuetify/iconsets/mdi-svg'
export default createVuetify({
// components,
// directives,
icons: {
defaultSet: 'mdi',
},
// ssr: false,
theme: {
defaultTheme: "dark",
themes: {
dark: {
colors: {
primary: colors.blue.darken2,
accent: colors.grey.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3
}
}
}
}
});

View File

@@ -0,0 +1,78 @@
import { EventEmitter } from 'events';
class WebSocketClient {
constructor() {
this.url = null;
this.socket = null;
this.reconnectInterval = 5000;
this.eventEmitter = new EventEmitter(); // Ajouter l'EventEmitter
}
connect(url) {
this.url = url;
this.socket = new window.WebSocket(this.url);
this.socket.onopen = () => {
console.log('WebSocket connected');
this.eventEmitter.emit('connect');
};
this.socket.onmessage = (message) => {
// console.log('Message received:', message.data);
// Émettre l'événement 'message' avec les données reçues
this.eventEmitter.emit('message', message.data);
this.handleMessage(message.data);
};
this.socket.onclose = () => {
console.log('WebSocket disconnected, retrying in 5 seconds...');
this.eventEmitter.emit('disconnect');
setTimeout(() => this.connect(this.url), this.reconnectInterval);
};
this.socket.onerror = (error) => {
console.error('WebSocket error:', error);
this.eventEmitter.emit('error', error);
this.socket.close();
};
}
handleMessage(rawData){
try {
const parsedData = JSON.parse(rawData);
this.eventEmitter.emit('json_message', parsedData);
if("context" in parsedData){
this.eventEmitter.emit(parsedData.context, parsedData);
}
return parsedData;
} catch (error) {
console.error('Failed to parse message as JSON:', error);
this.eventEmitter.emit('invalid_message', { raw: rawData, error });
return null;
}
}
// Méthodes pour gérer les événements
on(event, callback) {
this.eventEmitter.on(event, callback);
}
off(event, callback) {
this.eventEmitter.off(event, callback);
}
send(data) {
if (this.socket.readyState === WebSocket.OPEN) {
this.socket.send(data);
} else {
console.error('WebSocket is not open. Cannot send data.');
}
}
}
export default {
install: (app, options) => {
app.config.globalProperties.$ws = new WebSocketClient();
}
}

View File

@@ -0,0 +1,51 @@
import {defineConfig, loadEnv} from "vite";
import {resolve, join} from "path";
import vue from "@vitejs/plugin-vue";
import vuetify from "vite-plugin-vuetify";
export default defineConfig((mode) => {
const env = loadEnv(mode, "..", ""),
SRC_DIR = resolve("./src"),
OUT_DIR = resolve("./dist")
return {
plugins: [
vue(),
vuetify()
],
resolve: {
alias: {
"@": resolve(SRC_DIR),
"vue": "vue/dist/vue.esm-bundler.js"
}
},
root: SRC_DIR,
base: "/static/",
css: {
postcss: "./postcss.config.js"
},
server: {
host: "0.0.0.0",
port: env.DEV_SERVER_PORT,
origin: `http://${env.DEV_SERVER_HOST}:${env.DEV_SERVER_PORT}`, // hotfix, webfont was loaded from wrong url
watch: {
usePolling: true,
reloadDelay: 500,
}
},
build: {
manifest: "manifest.json",
emptyOutDir: true,
outDir: OUT_DIR,
rollupOptions: {
input: {
// admin: join(SRC_DIR, "app/admin-entrypoint.js"),
login: join(SRC_DIR, "app/login.js"),
// main: join(SRC_DIR, "app/main-entrypoint.js"),
torrent: join(SRC_DIR, "app/torrent.js"),
// style: join(SRC_DIR, "style/main.css.js")
}
}
}
}
})

840
app/frontend/yarn.lock Normal file
View File

@@ -0,0 +1,840 @@
# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
# yarn lockfile v1
"@babel/helper-string-parser@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c"
integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==
"@babel/helper-validator-identifier@^7.25.9":
version "7.25.9"
resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7"
integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==
"@babel/parser@^7.25.3":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.26.9.tgz#d9e78bee6dc80f9efd8f2349dcfbbcdace280fd5"
integrity sha512-81NWa1njQblgZbQHxWHpxxCzNsa3ZwvFqpUg7P+NNUU6f3UU2jBEg4OlF/J6rl8+PQGh1q6/zWScd001YwcA5A==
dependencies:
"@babel/types" "^7.26.9"
"@babel/runtime@^7.11.2", "@babel/runtime@^7.12.5", "@babel/runtime@^7.5.5":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.26.9.tgz#aa4c6facc65b9cb3f87d75125ffd47781b475433"
integrity sha512-aA63XwOkcl4xxQa3HjPMqOP6LiK0ZDv3mUPYEFXkpHbaFjtGggE1A61FjFzJnB+p7/oy2gA8E+rcBNl/zC1tMg==
dependencies:
regenerator-runtime "^0.14.0"
"@babel/types@^7.26.9":
version "7.26.9"
resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.9.tgz#08b43dec79ee8e682c2ac631c010bdcac54a21ce"
integrity sha512-Y3IR1cRnOxOCDvMmNiym7XpXQ93iGDDPHx+Zj+NM+rg0fBaShfQLkg+hKPaZCEvg5N/LeCo4+Rj/i3FuJsIQaw==
dependencies:
"@babel/helper-string-parser" "^7.25.9"
"@babel/helper-validator-identifier" "^7.25.9"
"@esbuild/aix-ppc64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.24.2.tgz#38848d3e25afe842a7943643cbcd387cc6e13461"
integrity sha512-thpVCb/rhxE/BnMLQ7GReQLLN8q9qbHmI55F4489/ByVg2aQaQ6kbcLb6FHkocZzQhxc4gx0sCk0tJkKBFzDhA==
"@esbuild/android-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.24.2.tgz#f592957ae8b5643129fa889c79e69cd8669bb894"
integrity sha512-cNLgeqCqV8WxfcTIOeL4OAtSmL8JjcN6m09XIgro1Wi7cF4t/THaWEa7eL5CMoMBdjoHOTh/vwTO/o2TRXIyzg==
"@esbuild/android-arm@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.24.2.tgz#72d8a2063aa630308af486a7e5cbcd1e134335b3"
integrity sha512-tmwl4hJkCfNHwFB3nBa8z1Uy3ypZpxqxfTQOcHX+xRByyYgunVbZ9MzUUfb0RxaHIMnbHagwAxuTL+tnNM+1/Q==
"@esbuild/android-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.24.2.tgz#9a7713504d5f04792f33be9c197a882b2d88febb"
integrity sha512-B6Q0YQDqMx9D7rvIcsXfmJfvUYLoP722bgfBlO5cGvNVb5V/+Y7nhBE3mHV9OpxBf4eAS2S68KZztiPaWq4XYw==
"@esbuild/darwin-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.24.2.tgz#02ae04ad8ebffd6e2ea096181b3366816b2b5936"
integrity sha512-kj3AnYWc+CekmZnS5IPu9D+HWtUI49hbnyqk0FLEJDbzCIQt7hg7ucF1SQAilhtYpIujfaHr6O0UHlzzSPdOeA==
"@esbuild/darwin-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.24.2.tgz#9ec312bc29c60e1b6cecadc82bd504d8adaa19e9"
integrity sha512-WeSrmwwHaPkNR5H3yYfowhZcbriGqooyu3zI/3GGpF8AyUdsrrP0X6KumITGA9WOyiJavnGZUwPGvxvwfWPHIA==
"@esbuild/freebsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.24.2.tgz#5e82f44cb4906d6aebf24497d6a068cfc152fa00"
integrity sha512-UN8HXjtJ0k/Mj6a9+5u6+2eZ2ERD7Edt1Q9IZiB5UZAIdPnVKDoG7mdTVGhHJIeEml60JteamR3qhsr1r8gXvg==
"@esbuild/freebsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.24.2.tgz#3fb1ce92f276168b75074b4e51aa0d8141ecce7f"
integrity sha512-TvW7wE/89PYW+IevEJXZ5sF6gJRDY/14hyIGFXdIucxCsbRmLUcjseQu1SyTko+2idmCw94TgyaEZi9HUSOe3Q==
"@esbuild/linux-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.24.2.tgz#856b632d79eb80aec0864381efd29de8fd0b1f43"
integrity sha512-7HnAD6074BW43YvvUmE/35Id9/NB7BeX5EoNkK9obndmZBUk8xmJJeU7DwmUeN7tkysslb2eSl6CTrYz6oEMQg==
"@esbuild/linux-arm@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.24.2.tgz#c846b4694dc5a75d1444f52257ccc5659021b736"
integrity sha512-n0WRM/gWIdU29J57hJyUdIsk0WarGd6To0s+Y+LwvlC55wt+GT/OgkwoXCXvIue1i1sSNWblHEig00GBWiJgfA==
"@esbuild/linux-ia32@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.24.2.tgz#f8a16615a78826ccbb6566fab9a9606cfd4a37d5"
integrity sha512-sfv0tGPQhcZOgTKO3oBE9xpHuUqguHvSo4jl+wjnKwFpapx+vUDcawbwPNuBIAYdRAvIDBfZVvXprIj3HA+Ugw==
"@esbuild/linux-loong64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.24.2.tgz#1c451538c765bf14913512c76ed8a351e18b09fc"
integrity sha512-CN9AZr8kEndGooS35ntToZLTQLHEjtVB5n7dl8ZcTZMonJ7CCfStrYhrzF97eAecqVbVJ7APOEe18RPI4KLhwQ==
"@esbuild/linux-mips64el@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.24.2.tgz#0846edeefbc3d8d50645c51869cc64401d9239cb"
integrity sha512-iMkk7qr/wl3exJATwkISxI7kTcmHKE+BlymIAbHO8xanq/TjHaaVThFF6ipWzPHryoFsesNQJPE/3wFJw4+huw==
"@esbuild/linux-ppc64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.24.2.tgz#8e3fc54505671d193337a36dfd4c1a23b8a41412"
integrity sha512-shsVrgCZ57Vr2L8mm39kO5PPIb+843FStGt7sGGoqiiWYconSxwTiuswC1VJZLCjNiMLAMh34jg4VSEQb+iEbw==
"@esbuild/linux-riscv64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.24.2.tgz#6a1e92096d5e68f7bb10a0d64bb5b6d1daf9a694"
integrity sha512-4eSFWnU9Hhd68fW16GD0TINewo1L6dRrB+oLNNbYyMUAeOD2yCK5KXGK1GH4qD/kT+bTEXjsyTCiJGHPZ3eM9Q==
"@esbuild/linux-s390x@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.24.2.tgz#ab18e56e66f7a3c49cb97d337cd0a6fea28a8577"
integrity sha512-S0Bh0A53b0YHL2XEXC20bHLuGMOhFDO6GN4b3YjRLK//Ep3ql3erpNcPlEFed93hsQAjAQDNsvcK+hV90FubSw==
"@esbuild/linux-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.24.2.tgz#8140c9b40da634d380b0b29c837a0b4267aff38f"
integrity sha512-8Qi4nQcCTbLnK9WoMjdC9NiTG6/E38RNICU6sUNqK0QFxCYgoARqVqxdFmWkdonVsvGqWhmm7MO0jyTqLqwj0Q==
"@esbuild/netbsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.24.2.tgz#65f19161432bafb3981f5f20a7ff45abb2e708e6"
integrity sha512-wuLK/VztRRpMt9zyHSazyCVdCXlpHkKm34WUyinD2lzK07FAHTq0KQvZZlXikNWkDGoT6x3TD51jKQ7gMVpopw==
"@esbuild/netbsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.24.2.tgz#7a3a97d77abfd11765a72f1c6f9b18f5396bcc40"
integrity sha512-VefFaQUc4FMmJuAxmIHgUmfNiLXY438XrL4GDNV1Y1H/RW3qow68xTwjZKfj/+Plp9NANmzbH5R40Meudu8mmw==
"@esbuild/openbsd-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.24.2.tgz#58b00238dd8f123bfff68d3acc53a6ee369af89f"
integrity sha512-YQbi46SBct6iKnszhSvdluqDmxCJA+Pu280Av9WICNwQmMxV7nLRHZfjQzwbPs3jeWnuAhE9Jy0NrnJ12Oz+0A==
"@esbuild/openbsd-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.24.2.tgz#0ac843fda0feb85a93e288842936c21a00a8a205"
integrity sha512-+iDS6zpNM6EnJyWv0bMGLWSWeXGN/HTaF/LXHXHwejGsVi+ooqDfMCCTerNFxEkM3wYVcExkeGXNqshc9iMaOA==
"@esbuild/sunos-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.24.2.tgz#8b7aa895e07828d36c422a4404cc2ecf27fb15c6"
integrity sha512-hTdsW27jcktEvpwNHJU4ZwWFGkz2zRJUz8pvddmXPtXDzVKTTINmlmga3ZzwcuMpUvLw7JkLy9QLKyGpD2Yxig==
"@esbuild/win32-arm64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.24.2.tgz#c023afb647cabf0c3ed13f0eddfc4f1d61c66a85"
integrity sha512-LihEQ2BBKVFLOC9ZItT9iFprsE9tqjDjnbulhHoFxYQtQfai7qfluVODIYxt1PgdoyQkz23+01rzwNwYfutxUQ==
"@esbuild/win32-ia32@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.24.2.tgz#96c356132d2dda990098c8b8b951209c3cd743c2"
integrity sha512-q+iGUwfs8tncmFC9pcnD5IvRHAzmbwQ3GPS5/ceCyHdjXubwQWI12MKWSNSMYLJMq23/IUCvJMS76PDqXe1fxA==
"@esbuild/win32-x64@0.24.2":
version "0.24.2"
resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.24.2.tgz#34aa0b52d0fbb1a654b596acfa595f0c7b77a77b"
integrity sha512-7VTgWzgMGvup6aSqDPLiW5zHaxYJGTO4OokMjIlrCtf+VpEL+cXKtCvg723iguPYI5oaUNdS+/V7OU2gvXVWEg==
"@jridgewell/sourcemap-codec@^1.5.0":
version "1.5.0"
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a"
integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==
"@mdi/font@^7.4.47":
version "7.4.47"
resolved "https://registry.yarnpkg.com/@mdi/font/-/font-7.4.47.tgz#2ae522867da3a5c88b738d54b403eb91471903af"
integrity sha512-43MtGpd585SNzHZPcYowu/84Vz2a2g31TvPMTm9uTiCSWzaheQySUcSyUH/46fPnuPQWof2yd0pGBtzee/IQWw==
"@rollup/rollup-android-arm-eabi@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.8.tgz#731df27dfdb77189547bcef96ada7bf166bbb2fb"
integrity sha512-q217OSE8DTp8AFHuNHXo0Y86e1wtlfVrXiAlwkIvGRQv9zbc6mE3sjIVfwI8sYUyNxwOg0j/Vm1RKM04JcWLJw==
"@rollup/rollup-android-arm64@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.8.tgz#4bea6db78e1f6927405df7fe0faf2f5095e01343"
integrity sha512-Gigjz7mNWaOL9wCggvoK3jEIUUbGul656opstjaUSGC3eT0BM7PofdAJaBfPFWWkXNVAXbaQtC99OCg4sJv70Q==
"@rollup/rollup-darwin-arm64@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.8.tgz#a7aab77d44be3c44a20f946e10160f84e5450e7f"
integrity sha512-02rVdZ5tgdUNRxIUrFdcMBZQoaPMrxtwSb+/hOfBdqkatYHR3lZ2A2EGyHq2sGOd0Owk80oV3snlDASC24He3Q==
"@rollup/rollup-darwin-x64@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.8.tgz#c572c024b57ee8ddd1b0851703ace9eb6cc0dd82"
integrity sha512-qIP/elwR/tq/dYRx3lgwK31jkZvMiD6qUtOycLhTzCvrjbZ3LjQnEM9rNhSGpbLXVJYQ3rq39A6Re0h9tU2ynw==
"@rollup/rollup-freebsd-arm64@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.8.tgz#cf74f8113b5a83098a5c026c165742277cbfb88b"
integrity sha512-IQNVXL9iY6NniYbTaOKdrlVP3XIqazBgJOVkddzJlqnCpRi/yAeSOa8PLcECFSQochzqApIOE1GHNu3pCz+BDA==
"@rollup/rollup-freebsd-x64@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.8.tgz#39561f3a2f201a4ad6a01425b1ff5928154ecd7c"
integrity sha512-TYXcHghgnCqYFiE3FT5QwXtOZqDj5GmaFNTNt3jNC+vh22dc/ukG2cG+pi75QO4kACohZzidsq7yKTKwq/Jq7Q==
"@rollup/rollup-linux-arm-gnueabihf@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.8.tgz#980d6061e373bfdaeb67925c46d2f8f9b3de537f"
integrity sha512-A4iphFGNkWRd+5m3VIGuqHnG3MVnqKe7Al57u9mwgbyZ2/xF9Jio72MaY7xxh+Y87VAHmGQr73qoKL9HPbXj1g==
"@rollup/rollup-linux-arm-musleabihf@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.8.tgz#f91a90f30dc00d5a64ac2d9bbedc829cd3cfaa78"
integrity sha512-S0lqKLfTm5u+QTxlFiAnb2J/2dgQqRy/XvziPtDd1rKZFXHTyYLoVL58M/XFwDI01AQCDIevGLbQrMAtdyanpA==
"@rollup/rollup-linux-arm64-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.8.tgz#fac700fa5c38bc13a0d5d34463133093da4c92a0"
integrity sha512-jpz9YOuPiSkL4G4pqKrus0pn9aYwpImGkosRKwNi+sJSkz+WU3anZe6hi73StLOQdfXYXC7hUfsQlTnjMd3s1A==
"@rollup/rollup-linux-arm64-musl@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.8.tgz#f50ecccf8c78841ff6df1706bc4782d7f62bf9c3"
integrity sha512-KdSfaROOUJXgTVxJNAZ3KwkRc5nggDk+06P6lgi1HLv1hskgvxHUKZ4xtwHkVYJ1Rep4GNo+uEfycCRRxht7+Q==
"@rollup/rollup-linux-loongarch64-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.8.tgz#5869dc0b28242da6553e2b52af41374f4038cd6e"
integrity sha512-NyF4gcxwkMFRjgXBM6g2lkT58OWztZvw5KkV2K0qqSnUEqCVcqdh2jN4gQrTn/YUpAcNKyFHfoOZEer9nwo6uQ==
"@rollup/rollup-linux-powerpc64le-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.8.tgz#5cdd9f851ce1bea33d6844a69f9574de335f20b1"
integrity sha512-LMJc999GkhGvktHU85zNTDImZVUCJ1z/MbAJTnviiWmmjyckP5aQsHtcujMjpNdMZPT2rQEDBlJfubhs3jsMfw==
"@rollup/rollup-linux-riscv64-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.8.tgz#ef5dc37f4388f5253f0def43e1440ec012af204d"
integrity sha512-xAQCAHPj8nJq1PI3z8CIZzXuXCstquz7cIOL73HHdXiRcKk8Ywwqtx2wrIy23EcTn4aZ2fLJNBB8d0tQENPCmw==
"@rollup/rollup-linux-s390x-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.8.tgz#7dbc3ccbcbcfb3e65be74538dfb6e8dd16178fde"
integrity sha512-DdePVk1NDEuc3fOe3dPPTb+rjMtuFw89gw6gVWxQFAuEqqSdDKnrwzZHrUYdac7A7dXl9Q2Vflxpme15gUWQFA==
"@rollup/rollup-linux-x64-gnu@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.8.tgz#5783fc0adcab7dc069692056e8ca8d83709855ce"
integrity sha512-8y7ED8gjxITUltTUEJLQdgpbPh1sUQ0kMTmufRF/Ns5tI9TNMNlhWtmPKKHCU0SilX+3MJkZ0zERYYGIVBYHIA==
"@rollup/rollup-linux-x64-musl@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.8.tgz#00b6c29b298197a384e3c659910b47943003a678"
integrity sha512-SCXcP0ZpGFIe7Ge+McxY5zKxiEI5ra+GT3QRxL0pMMtxPfpyLAKleZODi1zdRHkz5/BhueUrYtYVgubqe9JBNQ==
"@rollup/rollup-win32-arm64-msvc@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.8.tgz#cbfee01f1fe73791c35191a05397838520ca3cdd"
integrity sha512-YHYsgzZgFJzTRbth4h7Or0m5O74Yda+hLin0irAIobkLQFRQd1qWmnoVfwmKm9TXIZVAD0nZ+GEb2ICicLyCnQ==
"@rollup/rollup-win32-ia32-msvc@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.8.tgz#95cdbdff48fe6c948abcf6a1d500b2bd5ce33f62"
integrity sha512-r3NRQrXkHr4uWy5TOjTpTYojR9XmF0j/RYgKCef+Ag46FWUTltm5ziticv8LdNsDMehjJ543x/+TJAek/xBA2w==
"@rollup/rollup-win32-x64-msvc@4.34.8":
version "4.34.8"
resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.8.tgz#4cdb2cfae69cdb7b1a3cc58778e820408075e928"
integrity sha512-U0FaE5O1BCpZSeE6gBl3c5ObhePQSfk9vDRToMmTkbhCOgW4jqvtS5LGyQ76L1fH8sM0keRp4uDTsbjiUyjk0g==
"@types/estree@1.0.6":
version "1.0.6"
resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.6.tgz#628effeeae2064a1b4e79f78e81d87b7e5fc7b50"
integrity sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==
"@videojs/http-streaming@^3.16.2":
version "3.17.0"
resolved "https://registry.yarnpkg.com/@videojs/http-streaming/-/http-streaming-3.17.0.tgz#58433aa72206afae2bb65462f023d21afd766bf4"
integrity sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^4.1.1"
aes-decrypter "^4.0.2"
global "^4.4.0"
m3u8-parser "^7.2.0"
mpd-parser "^1.3.1"
mux.js "7.1.0"
video.js "^7 || ^8"
"@videojs/vhs-utils@^4.0.0":
version "4.0.0"
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-4.0.0.tgz#4d4dbf5d61a9fbd2da114b84ec747c3a483bc60d"
integrity sha512-xJp7Yd4jMLwje2vHCUmi8MOUU76nxiwII3z4Eg3Ucb+6rrkFVGosrXlMgGnaLjq724j3wzNElRZ71D/CKrTtxg==
dependencies:
"@babel/runtime" "^7.12.5"
global "^4.4.0"
url-toolkit "^2.2.1"
"@videojs/vhs-utils@^4.1.1":
version "4.1.1"
resolved "https://registry.yarnpkg.com/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz#44226fc5993f577490b5e08951ddc083714405cc"
integrity sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==
dependencies:
"@babel/runtime" "^7.12.5"
global "^4.4.0"
"@videojs/xhr@2.7.0":
version "2.7.0"
resolved "https://registry.yarnpkg.com/@videojs/xhr/-/xhr-2.7.0.tgz#e272af6e2b5448aeb400905a5c6f4818f6b6ad47"
integrity sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==
dependencies:
"@babel/runtime" "^7.5.5"
global "~4.4.0"
is-function "^1.0.1"
"@vitejs/plugin-vue@^5.2.1":
version "5.2.1"
resolved "https://registry.yarnpkg.com/@vitejs/plugin-vue/-/plugin-vue-5.2.1.tgz#d1491f678ee3af899f7ae57d9c21dc52a65c7133"
integrity sha512-cxh314tzaWwOLqVes2gnnCtvBDcM1UMdn+iFR+UjAn411dPT3tOmqrJjbMd7koZpMAmBM/GqeV4n9ge7JSiJJQ==
"@vue/compiler-core@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/compiler-core/-/compiler-core-3.5.13.tgz#b0ae6c4347f60c03e849a05d34e5bf747c9bda05"
integrity sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==
dependencies:
"@babel/parser" "^7.25.3"
"@vue/shared" "3.5.13"
entities "^4.5.0"
estree-walker "^2.0.2"
source-map-js "^1.2.0"
"@vue/compiler-dom@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz#bb1b8758dbc542b3658dda973b98a1c9311a8a58"
integrity sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==
dependencies:
"@vue/compiler-core" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/compiler-sfc@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz#461f8bd343b5c06fac4189c4fef8af32dea82b46"
integrity sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==
dependencies:
"@babel/parser" "^7.25.3"
"@vue/compiler-core" "3.5.13"
"@vue/compiler-dom" "3.5.13"
"@vue/compiler-ssr" "3.5.13"
"@vue/shared" "3.5.13"
estree-walker "^2.0.2"
magic-string "^0.30.11"
postcss "^8.4.48"
source-map-js "^1.2.0"
"@vue/compiler-ssr@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz#e771adcca6d3d000f91a4277c972a996d07f43ba"
integrity sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==
dependencies:
"@vue/compiler-dom" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/reactivity@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/reactivity/-/reactivity-3.5.13.tgz#b41ff2bb865e093899a22219f5b25f97b6fe155f"
integrity sha512-NaCwtw8o48B9I6L1zl2p41OHo/2Z4wqYGGIK1Khu5T7yxrn+ATOixn/Udn2m+6kZKB/J7cuT9DbWWhRxqixACg==
dependencies:
"@vue/shared" "3.5.13"
"@vue/runtime-core@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/runtime-core/-/runtime-core-3.5.13.tgz#1fafa4bf0b97af0ebdd9dbfe98cd630da363a455"
integrity sha512-Fj4YRQ3Az0WTZw1sFe+QDb0aXCerigEpw418pw1HBUKFtnQHWzwojaukAs2X/c9DQz4MQ4bsXTGlcpGxU/RCIw==
dependencies:
"@vue/reactivity" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/runtime-dom@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/runtime-dom/-/runtime-dom-3.5.13.tgz#610fc795de9246300e8ae8865930d534e1246215"
integrity sha512-dLaj94s93NYLqjLiyFzVs9X6dWhTdAlEAciC3Moq7gzAc13VJUdCnjjRurNM6uTLFATRHexHCTu/Xp3eW6yoog==
dependencies:
"@vue/reactivity" "3.5.13"
"@vue/runtime-core" "3.5.13"
"@vue/shared" "3.5.13"
csstype "^3.1.3"
"@vue/server-renderer@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/server-renderer/-/server-renderer-3.5.13.tgz#429ead62ee51de789646c22efe908e489aad46f7"
integrity sha512-wAi4IRJV/2SAW3htkTlB+dHeRmpTiVIK1OGLWV1yeStVSebSQQOwGwIq0D3ZIoBj2C2qpgz5+vX9iEBkTdk5YA==
dependencies:
"@vue/compiler-ssr" "3.5.13"
"@vue/shared" "3.5.13"
"@vue/shared@3.5.13":
version "3.5.13"
resolved "https://registry.yarnpkg.com/@vue/shared/-/shared-3.5.13.tgz#87b309a6379c22b926e696893237826f64339b6f"
integrity sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==
"@vuetify/loader-shared@^2.1.0":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@vuetify/loader-shared/-/loader-shared-2.1.0.tgz#29410dce04a78fa9cd40c4d9bc417b8d61ce5103"
integrity sha512-dNE6Ceym9ijFsmJKB7YGW0cxs7xbYV8+1LjU6jd4P14xOt/ji4Igtgzt0rJFbxu+ZhAzqz853lhB0z8V9Dy9cQ==
dependencies:
upath "^2.0.1"
"@xmldom/xmldom@^0.8.3":
version "0.8.10"
resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
aes-decrypter@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/aes-decrypter/-/aes-decrypter-4.0.2.tgz#90648181c68878f54093920a3b44776ec2dc4914"
integrity sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^4.1.1"
global "^4.4.0"
pkcs7 "^1.0.4"
autoprefixer@^10.4.20:
version "10.4.20"
resolved "https://registry.yarnpkg.com/autoprefixer/-/autoprefixer-10.4.20.tgz#5caec14d43976ef42e32dcb4bd62878e96be5b3b"
integrity sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==
dependencies:
browserslist "^4.23.3"
caniuse-lite "^1.0.30001646"
fraction.js "^4.3.7"
normalize-range "^0.1.2"
picocolors "^1.0.1"
postcss-value-parser "^4.2.0"
browserslist@^4.23.3:
version "4.24.4"
resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b"
integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A==
dependencies:
caniuse-lite "^1.0.30001688"
electron-to-chromium "^1.5.73"
node-releases "^2.0.19"
update-browserslist-db "^1.1.1"
caniuse-lite@^1.0.30001646, caniuse-lite@^1.0.30001688:
version "1.0.30001700"
resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001700.tgz#26cd429cf09b4fd4e745daf4916039c794d720f6"
integrity sha512-2S6XIXwaE7K7erT8dY+kLQcpa5ms63XlRkMkReXjle+kf6c5g38vyMl+Z5y8dSxOFDhcFe+nxnn261PLxBSQsQ==
csstype@^3.1.3:
version "3.1.3"
resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81"
integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==
debug@^4.3.3:
version "4.4.0"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a"
integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==
dependencies:
ms "^2.1.3"
dom-walk@^0.1.0:
version "0.1.2"
resolved "https://registry.yarnpkg.com/dom-walk/-/dom-walk-0.1.2.tgz#0c548bef048f4d1f2a97249002236060daa3fd84"
integrity sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==
electron-to-chromium@^1.5.73:
version "1.5.101"
resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.101.tgz#c26490fb2c1363d804e798e138a2a544fc7f7075"
integrity sha512-L0ISiQrP/56Acgu4/i/kfPwWSgrzYZUnQrC0+QPFuhqlLP1Ir7qzPPDVS9BcKIyWTRU8+o6CC8dKw38tSWhYIA==
entities@^4.5.0:
version "4.5.0"
resolved "https://registry.yarnpkg.com/entities/-/entities-4.5.0.tgz#5d268ea5e7113ec74c4d033b79ea5a35a488fb48"
integrity sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==
esbuild@^0.24.2:
version "0.24.2"
resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.24.2.tgz#b5b55bee7de017bff5fb8a4e3e44f2ebe2c3567d"
integrity sha512-+9egpBW8I3CD5XPe0n6BfT5fxLzxrlDzqydF3aviG+9ni1lDC/OvMHcxqEFV0+LANZG5R1bFMWfUrjVsdwxJvA==
optionalDependencies:
"@esbuild/aix-ppc64" "0.24.2"
"@esbuild/android-arm" "0.24.2"
"@esbuild/android-arm64" "0.24.2"
"@esbuild/android-x64" "0.24.2"
"@esbuild/darwin-arm64" "0.24.2"
"@esbuild/darwin-x64" "0.24.2"
"@esbuild/freebsd-arm64" "0.24.2"
"@esbuild/freebsd-x64" "0.24.2"
"@esbuild/linux-arm" "0.24.2"
"@esbuild/linux-arm64" "0.24.2"
"@esbuild/linux-ia32" "0.24.2"
"@esbuild/linux-loong64" "0.24.2"
"@esbuild/linux-mips64el" "0.24.2"
"@esbuild/linux-ppc64" "0.24.2"
"@esbuild/linux-riscv64" "0.24.2"
"@esbuild/linux-s390x" "0.24.2"
"@esbuild/linux-x64" "0.24.2"
"@esbuild/netbsd-arm64" "0.24.2"
"@esbuild/netbsd-x64" "0.24.2"
"@esbuild/openbsd-arm64" "0.24.2"
"@esbuild/openbsd-x64" "0.24.2"
"@esbuild/sunos-x64" "0.24.2"
"@esbuild/win32-arm64" "0.24.2"
"@esbuild/win32-ia32" "0.24.2"
"@esbuild/win32-x64" "0.24.2"
escalade@^3.2.0:
version "3.2.0"
resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5"
integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==
estree-walker@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/estree-walker/-/estree-walker-2.0.2.tgz#52f010178c2a4c117a7757cfe942adb7d2da4cac"
integrity sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==
events@^3.3.0:
version "3.3.0"
resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400"
integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==
filesize@^10.1.6:
version "10.1.6"
resolved "https://registry.yarnpkg.com/filesize/-/filesize-10.1.6.tgz#31194da825ac58689c0bce3948f33ce83aabd361"
integrity sha512-sJslQKU2uM33qH5nqewAwVB2QgR6w1aMNsYUp3aN5rMRyXEwJGmZvaWzeJFNTOXWlHQyBFCWrdj3fV/fsTOX8w==
fraction.js@^4.3.7:
version "4.3.7"
resolved "https://registry.yarnpkg.com/fraction.js/-/fraction.js-4.3.7.tgz#06ca0085157e42fda7f9e726e79fefc4068840f7"
integrity sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==
fsevents@~2.3.2, fsevents@~2.3.3:
version "2.3.3"
resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6"
integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==
function-bind@^1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c"
integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==
global@4.4.0, global@^4.3.1, global@^4.4.0, global@~4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/global/-/global-4.4.0.tgz#3e7b105179006a323ed71aafca3e9c57a5cc6406"
integrity sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==
dependencies:
min-document "^2.19.0"
process "^0.11.10"
hasown@^2.0.2:
version "2.0.2"
resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003"
integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==
dependencies:
function-bind "^1.1.2"
is-core-module@^2.16.0:
version "2.16.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.16.1.tgz#2a98801a849f43e2add644fbb6bc6229b19a4ef4"
integrity sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==
dependencies:
hasown "^2.0.2"
is-function@^1.0.1:
version "1.0.2"
resolved "https://registry.yarnpkg.com/is-function/-/is-function-1.0.2.tgz#4f097f30abf6efadac9833b17ca5dc03f8144e08"
integrity sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==
js-cookie@^3.0.5:
version "3.0.5"
resolved "https://registry.yarnpkg.com/js-cookie/-/js-cookie-3.0.5.tgz#0b7e2fd0c01552c58ba86e0841f94dc2557dcdbc"
integrity sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==
m3u8-parser@^7.2.0:
version "7.2.0"
resolved "https://registry.yarnpkg.com/m3u8-parser/-/m3u8-parser-7.2.0.tgz#9e2eb50abb8349d248cd58842367da4acabdf297"
integrity sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^4.1.1"
global "^4.4.0"
magic-string@^0.30.11:
version "0.30.17"
resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453"
integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==
dependencies:
"@jridgewell/sourcemap-codec" "^1.5.0"
min-document@^2.19.0:
version "2.19.0"
resolved "https://registry.yarnpkg.com/min-document/-/min-document-2.19.0.tgz#7bd282e3f5842ed295bb748cdd9f1ffa2c824685"
integrity sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==
dependencies:
dom-walk "^0.1.0"
moment@^2.30.1:
version "2.30.1"
resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae"
integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==
mpd-parser@^1.3.1:
version "1.3.1"
resolved "https://registry.yarnpkg.com/mpd-parser/-/mpd-parser-1.3.1.tgz#557b6ac27411c2c177bb01e46e14440703a414a3"
integrity sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/vhs-utils" "^4.0.0"
"@xmldom/xmldom" "^0.8.3"
global "^4.4.0"
ms@^2.1.3:
version "2.1.3"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2"
integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==
mux.js@7.1.0, mux.js@^7.0.1:
version "7.1.0"
resolved "https://registry.yarnpkg.com/mux.js/-/mux.js-7.1.0.tgz#aba5ed55a39cb790ef4b30b2c3ea0d2630b0264e"
integrity sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==
dependencies:
"@babel/runtime" "^7.11.2"
global "^4.4.0"
nanoid@^3.3.8:
version "3.3.8"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf"
integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==
node-releases@^2.0.19:
version "2.0.19"
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314"
integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==
normalize-range@^0.1.2:
version "0.1.2"
resolved "https://registry.yarnpkg.com/normalize-range/-/normalize-range-0.1.2.tgz#2d10c06bdfd312ea9777695a4d28439456b75942"
integrity sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==
path-parse@^1.0.7:
version "1.0.7"
resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735"
integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==
picocolors@^1.0.1, picocolors@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b"
integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==
pify@^2.3.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/pify/-/pify-2.3.0.tgz#ed141a6ac043a849ea588498e7dca8b15330e90c"
integrity sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==
pkcs7@^1.0.4:
version "1.0.4"
resolved "https://registry.yarnpkg.com/pkcs7/-/pkcs7-1.0.4.tgz#6090b9e71160dabf69209d719cbafa538b00a1cb"
integrity sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==
dependencies:
"@babel/runtime" "^7.5.5"
postcss-import@^16.1.0:
version "16.1.0"
resolved "https://registry.yarnpkg.com/postcss-import/-/postcss-import-16.1.0.tgz#258732175518129667fe1e2e2a05b19b5654b96a"
integrity sha512-7hsAZ4xGXl4MW+OKEWCnF6T5jqBw80/EE9aXg1r2yyn1RsVEU8EtKXbijEODa+rg7iih4bKf7vlvTGYR4CnPNg==
dependencies:
postcss-value-parser "^4.0.0"
read-cache "^1.0.0"
resolve "^1.1.7"
postcss-simple-vars@^7.0.1:
version "7.0.1"
resolved "https://registry.yarnpkg.com/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz#836b3097a54dcd13dbd3c36a5dbdd512fad2954c"
integrity sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==
postcss-value-parser@^4.0.0, postcss-value-parser@^4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514"
integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==
postcss@^8.4.48, postcss@^8.5.1, postcss@^8.5.2:
version "8.5.2"
resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.2.tgz#e7b99cb9d2ec3e8dd424002e7c16517cb2b846bd"
integrity sha512-MjOadfU3Ys9KYoX0AdkBlFEF1Vx37uCCeN4ZHnmwm9FfpbsGWMZeBLMmmpY+6Ocqod7mkdZ0DT31OlbsFrLlkA==
dependencies:
nanoid "^3.3.8"
picocolors "^1.1.1"
source-map-js "^1.2.1"
process@^0.11.10:
version "0.11.10"
resolved "https://registry.yarnpkg.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
integrity sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==
read-cache@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/read-cache/-/read-cache-1.0.0.tgz#e664ef31161166c9751cdbe8dbcf86b5fb58f774"
integrity sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==
dependencies:
pify "^2.3.0"
regenerator-runtime@^0.14.0:
version "0.14.1"
resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f"
integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==
resolve@^1.1.7:
version "1.22.10"
resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.10.tgz#b663e83ffb09bbf2386944736baae803029b8b39"
integrity sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==
dependencies:
is-core-module "^2.16.0"
path-parse "^1.0.7"
supports-preserve-symlinks-flag "^1.0.0"
rollup@^4.30.1:
version "4.34.8"
resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.34.8.tgz#e859c1a51d899aba9bcf451d4eed1d11fb8e2a6e"
integrity sha512-489gTVMzAYdiZHFVA/ig/iYFllCcWFHMvUHI1rpFmkoUtRlQxqh6/yiNqnYibjMZ2b/+FUQwldG+aLsEt6bglQ==
dependencies:
"@types/estree" "1.0.6"
optionalDependencies:
"@rollup/rollup-android-arm-eabi" "4.34.8"
"@rollup/rollup-android-arm64" "4.34.8"
"@rollup/rollup-darwin-arm64" "4.34.8"
"@rollup/rollup-darwin-x64" "4.34.8"
"@rollup/rollup-freebsd-arm64" "4.34.8"
"@rollup/rollup-freebsd-x64" "4.34.8"
"@rollup/rollup-linux-arm-gnueabihf" "4.34.8"
"@rollup/rollup-linux-arm-musleabihf" "4.34.8"
"@rollup/rollup-linux-arm64-gnu" "4.34.8"
"@rollup/rollup-linux-arm64-musl" "4.34.8"
"@rollup/rollup-linux-loongarch64-gnu" "4.34.8"
"@rollup/rollup-linux-powerpc64le-gnu" "4.34.8"
"@rollup/rollup-linux-riscv64-gnu" "4.34.8"
"@rollup/rollup-linux-s390x-gnu" "4.34.8"
"@rollup/rollup-linux-x64-gnu" "4.34.8"
"@rollup/rollup-linux-x64-musl" "4.34.8"
"@rollup/rollup-win32-arm64-msvc" "4.34.8"
"@rollup/rollup-win32-ia32-msvc" "4.34.8"
"@rollup/rollup-win32-x64-msvc" "4.34.8"
fsevents "~2.3.2"
source-map-js@^1.2.0, source-map-js@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46"
integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==
supports-preserve-symlinks-flag@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09"
integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==
upath@^2.0.1:
version "2.0.1"
resolved "https://registry.yarnpkg.com/upath/-/upath-2.0.1.tgz#50c73dea68d6f6b990f51d279ce6081665d61a8b"
integrity sha512-1uEe95xksV1O0CYKXo8vQvN1JEbtJp7lb7C5U9HMsIp6IVwntkH/oNUzyVNQSd4S1sYk2FpSSW44FqMc8qee5w==
update-browserslist-db@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580"
integrity sha512-PPypAm5qvlD7XMZC3BujecnaOxwhrtoFR+Dqkk5Aa/6DssiH0ibKoketaj9w8LP7Bont1rYeoV5plxD7RTEPRg==
dependencies:
escalade "^3.2.0"
picocolors "^1.1.1"
url-toolkit@^2.2.1:
version "2.2.5"
resolved "https://registry.yarnpkg.com/url-toolkit/-/url-toolkit-2.2.5.tgz#58406b18e12c58803e14624df5e374f638b0f607"
integrity sha512-mtN6xk+Nac+oyJ/PrI7tzfmomRVNFIWKUbG8jdYFt52hxbiReFAXIjYskvu64/dvuW71IcB7lV8l0HvZMac6Jg==
"video.js@^7 || ^8", video.js@^8.21.0:
version "8.21.0"
resolved "https://registry.yarnpkg.com/video.js/-/video.js-8.21.0.tgz#ce097aa2cd06dcbada5379215e3781d703d9d16b"
integrity sha512-zcwerRb257QAuWfi8NH9yEX7vrGKFthjfcONmOQ4lxFRpDAbAi+u5LAjCjMWqhJda6zEmxkgdDpOMW3Y21QpXA==
dependencies:
"@babel/runtime" "^7.12.5"
"@videojs/http-streaming" "^3.16.2"
"@videojs/vhs-utils" "^4.1.1"
"@videojs/xhr" "2.7.0"
aes-decrypter "^4.0.2"
global "4.4.0"
m3u8-parser "^7.2.0"
mpd-parser "^1.3.1"
mux.js "^7.0.1"
videojs-contrib-quality-levels "4.1.0"
videojs-font "4.2.0"
videojs-vtt.js "0.15.5"
videojs-contrib-quality-levels@4.1.0:
version "4.1.0"
resolved "https://registry.yarnpkg.com/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz#44c2d2167114a5c8418548b10a25cb409d6cba51"
integrity sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==
dependencies:
global "^4.4.0"
videojs-font@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/videojs-font/-/videojs-font-4.2.0.tgz#fbce803d347c565816e296f527e208dc65c9f235"
integrity sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==
videojs-vtt.js@0.15.5:
version "0.15.5"
resolved "https://registry.yarnpkg.com/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz#567776eaf2a7a928d88b148a8b401ade2406f2ca"
integrity sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==
dependencies:
global "^4.3.1"
vite-plugin-vuetify@^2.1.0:
version "2.1.0"
resolved "https://registry.yarnpkg.com/vite-plugin-vuetify/-/vite-plugin-vuetify-2.1.0.tgz#56767be099fd18a44ec2f9831d49269722e0e538"
integrity sha512-4wEAQtZaigPpwbFcZbrKpYwutOsWwWdeXn22B9XHzDPQNxVsKT+K9lKcXZnI5JESO1Iaql48S9rOk8RZZEt+Mw==
dependencies:
"@vuetify/loader-shared" "^2.1.0"
debug "^4.3.3"
upath "^2.0.1"
vite@^6.1.0:
version "6.1.0"
resolved "https://registry.yarnpkg.com/vite/-/vite-6.1.0.tgz#00a4e99a23751af98a2e4701c65ba89ce23858a6"
integrity sha512-RjjMipCKVoR4hVfPY6GQTgveinjNuyLw+qruksLDvA5ktI1150VmcMBKmQaEWJhg/j6Uaf6dNCNA0AfdzUb/hQ==
dependencies:
esbuild "^0.24.2"
postcss "^8.5.1"
rollup "^4.30.1"
optionalDependencies:
fsevents "~2.3.3"
vue@^3.5.13:
version "3.5.13"
resolved "https://registry.yarnpkg.com/vue/-/vue-3.5.13.tgz#9f760a1a982b09c0c04a867903fc339c9f29ec0a"
integrity sha512-wmeiSMxkZCSc+PM2w2VRsOYAZC8GdipNFRTsLSfodVqI9mbejKeXEGr8SckuLnrQPGe3oJN5c3K0vpoU9q/wCQ==
dependencies:
"@vue/compiler-dom" "3.5.13"
"@vue/compiler-sfc" "3.5.13"
"@vue/runtime-dom" "3.5.13"
"@vue/server-renderer" "3.5.13"
"@vue/shared" "3.5.13"
vuetify@^3.7.12:
version "3.7.12"
resolved "https://registry.yarnpkg.com/vuetify/-/vuetify-3.7.12.tgz#17fa7e7a88ba8495d7162ad64916ea91e63875cf"
integrity sha512-cBxWXKPNl3vWc10/EEpfK4RBrCZERAHEUZCWmrJPd6v+JU0sbm4sEgIpy8IU5d1BzA1kIhknpbgYy2IqiZponA==