Files
dupe/client/src/components/Sidebar.svelte
2025-11-01 15:44:15 +03:00

215 lines
6.1 KiB
Svelte
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<script>
import { Link } from "svelte-routing";
import { createEventDispatcher, onDestroy, onMount, tick } from "svelte";
import { movieCount } from "../stores/movieStore.js";
import { tvShowCount } from "../stores/tvStore.js";
import { apiFetch } from "../utils/api.js";
export let menuOpen = false;
const dispatch = createEventDispatcher();
let hasMovies = false;
let hasShows = false;
// Svelte store kullanarak reaktivite sağla
import { writable } from 'svelte/store';
const diskSpaceStore = writable({ totalGB: '0', usedGB: '0', usedPercent: 0 });
let diskSpace;
// Store subscription'ı temizlemek için
let unsubscribeDiskSpace;
// Store'u değişkene bağla
unsubscribeDiskSpace = diskSpaceStore.subscribe(value => {
diskSpace = value;
console.log('🔄 Disk space updated from store:', diskSpace);
});
// Disk space'i reaktif olarak güncellemek için bir fonksiyon
function updateDiskSpace(newData) {
diskSpaceStore.update(current => Object.assign({}, current, newData));
console.log('🔄 Disk space update called with:', newData);
}
const unsubscribeMovie = movieCount.subscribe((count) => {
hasMovies = (count ?? 0) > 0;
});
const unsubscribeTv = tvShowCount.subscribe((count) => {
hasShows = (count ?? 0) > 0;
});
onDestroy(() => {
unsubscribeMovie();
unsubscribeTv();
if (unsubscribeDiskSpace) {
unsubscribeDiskSpace();
}
});
// Menü öğesine tıklanınca sidebar'ı kapat
function handleLinkClick() {
dispatch("closeMenu");
}
// Disk space bilgilerini al
async function fetchDiskSpace() {
try {
const response = await apiFetch('/api/disk-space');
if (response.ok) {
const data = await response.json();
console.log('Disk space data received:', data);
updateDiskSpace(data);
} else {
console.error('Disk space API error:', response.status, response.statusText);
}
} catch (error) {
console.error('Disk space fetch error:', error);
}
}
// Component yüklendiğinde disk space bilgilerini al
onMount(() => {
console.log('🔌 Sidebar component mounted');
fetchDiskSpace();
// WebSocket bağlantısı kur
const wsProtocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
// Server port'unu doğru almak için
const currentHost = window.location.host;
// Eğer client farklı portta çalışıyorsa, server port'unu manuel belirt
const wsHost = currentHost.includes(':3000') ? currentHost.replace(':3000', ':3001') : currentHost;
const wsUrl = `${wsProtocol}//${wsHost}`;
console.log('🔌 Connecting to WebSocket at:', wsUrl);
// WebSocket bağlantısını global olarak saklayalım
window.diskSpaceWs = new WebSocket(wsUrl);
window.diskSpaceWs.onmessage = (event) => {
try {
const data = JSON.parse(event.data);
console.log('WebSocket message received:', data);
if (data.type === 'diskSpace') {
console.log('Disk space update received:', data.data);
updateDiskSpace(data.data);
}
} catch (err) {
console.error('WebSocket message parse error:', err);
}
};
window.diskSpaceWs.onopen = () => {
console.log('WebSocket connected for disk space updates');
};
window.diskSpaceWs.onerror = (error) => {
console.error('WebSocket error:', error);
};
window.diskSpaceWs.onclose = () => {
console.log('WebSocket disconnected');
};
onDestroy(() => {
if (window.diskSpaceWs && (window.diskSpaceWs.readyState === WebSocket.OPEN || window.diskSpaceWs.readyState === WebSocket.CONNECTING)) {
window.diskSpaceWs.close();
}
});
});
</script>
<div class="sidebar" class:open={menuOpen}>
<div class="logo">du.pe</div>
<div class="menu">
<Link
to="/"
class="item"
getProps={({ isCurrent }) => ({
class: isCurrent ? "item active" : "item",
})}
on:click={handleLinkClick}
>
<i class="fa-solid fa-folder icon"></i>
Files
</Link>
{#if hasMovies}
<Link
to="/movies"
class="item"
getProps={({ isCurrent }) => ({
class: isCurrent ? "item active" : "item",
})}
on:click={handleLinkClick}
>
<i class="fa-solid fa-film icon"></i>
Movies
</Link>
{/if}
{#if hasShows}
<Link
to="/tv"
class="item"
getProps={({ isCurrent }) => ({
class: isCurrent ? "item active" : "item",
})}
on:click={handleLinkClick}
>
<i class="fa-solid fa-tv icon"></i>
Tv Shows
</Link>
{/if}
<Link
to="/transfers"
class="item"
getProps={({ isCurrent }) => ({
class: isCurrent ? "item active" : "item",
})}
on:click={handleLinkClick}
>
<i class="fa-solid fa-arrow-down icon"></i>
Transfers
</Link>
<Link
to="/trash"
class="item"
getProps={({ isCurrent }) => ({
class: isCurrent ? "item active" : "item",
})}
on:click={handleLinkClick}
>
<i class="fa-solid fa-trash icon"></i>
Trash
</Link>
</div>
<!-- Disk Space Alanı - Sidebar'ın en altında -->
<div class="disk-space">
<div class="disk-space-header">
<i class="fa-solid fa-hard-drive icon"></i>
<span class="disk-space-title">Disk Space</span>
</div>
<div class="disk-space-info">
<div class="disk-space-text">
<span class="disk-space-values">
{#if diskSpace.usedFormatted && diskSpace.totalFormatted}
{diskSpace.usedFormatted} / {diskSpace.totalFormatted}
{:else}
{diskSpace.usedGB} GB / {diskSpace.totalGB} GB
{/if}
</span>
</div>
<div class="disk-space-bar-container">
<div class="disk-space-bar">
<div
class="disk-space-bar-fill {diskSpace.usedPercent < 50 ? 'low' : diskSpace.usedPercent < 80 ? 'medium' : 'high'}"
style="width: {diskSpace.usedPercent}%"
></div>
</div>
</div>
</div>
</div>
</div>