Compare commits

...

2 Commits

Author SHA1 Message Date
569a7975de refactor(files): konum senkronizasyonunu sağlamlaştır
URL tabanlı konum yönetimini tek bir fonksiyon altında toplayarak
tarayıcı navigasyonu ve history API olaylarının tutarlı şekilde işlenmesini
sağla. pushState ve replaceState metodlarını patch ederek özel locationchange
olayı oluşturur ve bileşen yok edildiğinde patch işlemini geri alır.
2026-01-31 10:36:07 +03:00
5e6da2b445 chore(deps): client bağımlılıklarını güncelle 2026-01-31 10:35:28 +03:00
2 changed files with 1371 additions and 39 deletions

1292
client/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,5 @@
<script>
import { onMount, tick } from "svelte";
import { onDestroy, onMount, tick } from "svelte";
import MatchModal from "../components/MatchModal.svelte";
import { API, apiFetch, moveEntry, renameFolder, copyEntry } from "../utils/api.js";
import { cleanFileName, extractTitleAndYear } from "../utils/filename.js";
@@ -452,6 +452,7 @@
const VIEW_KEY = "filesViewMode";
let viewMode = "grid";
let initialPath = "";
let unpatchHistory = null;
if (typeof window !== "undefined") {
const storedView = window.localStorage.getItem(VIEW_KEY);
if (storedView === "grid" || storedView === "list") {
@@ -491,14 +492,16 @@
let clipboardItem = null;
let clipboardOperation = null; // 'cut' veya 'copy'
if (typeof window !== "undefined") {
const syncFromLocation = ({ replace = false } = {}) => {
if (typeof window === "undefined") return;
const params = new URLSearchParams(window.location.search);
const pathParam = params.get("path");
let nextPath = "";
if (pathParam) {
try {
initialPath = normalizePath(decodeURIComponent(pathParam));
nextPath = normalizePath(decodeURIComponent(pathParam));
} catch (err) {
initialPath = normalizePath(pathParam);
nextPath = normalizePath(pathParam);
}
}
const playParam = params.get("play");
@@ -509,16 +512,49 @@
pendingPlayTarget = playParam;
}
params.delete("play");
const search = params.toString();
const newUrl = `${window.location.pathname}${search ? `?${search}` : ""}${window.location.hash}`;
window.history.replaceState(
{ path: nextPath, originalPath: null },
"",
newUrl,
);
}
const search = params.toString();
const newUrl = `${window.location.pathname}${search ? `?${search}` : ""}${window.location.hash}`;
window.history.replaceState(
{ path: initialPath, originalPath: null },
"",
newUrl,
);
const state = window.history.state || {};
const nextOriginal =
typeof state.originalPath === "string"
? normalizePath(state.originalPath)
: resolveOriginalPathForDisplay(nextPath);
if (
normalizePath(currentPath) === nextPath &&
normalizePath(currentOriginalPath) === nextOriginal
) {
return;
}
const hadSearch = searchTerm.trim().length > 0;
const nextSearchTerm = hadSearch ? "" : searchTerm;
currentPath = nextPath;
currentOriginalPath = nextOriginal;
if (hadSearch) {
clearSearch("files");
}
selectedItems = new Set();
activeMenu = null;
if (isCreatingFolder) cancelCreateFolder();
updateVisibleState(files, nextPath);
renderedEntries = filterEntriesBySearch(visibleEntries, nextSearchTerm);
if (replace) {
updateUrlPath(nextPath, nextOriginal, { replace: true });
}
};
if (typeof window !== "undefined") {
syncFromLocation({ replace: true });
initialPath = currentPath;
}
currentPath = normalizePath(initialPath);
// 🎬 Player kontrolleri
let videoEl;
let isPlaying = false;
@@ -1694,34 +1730,37 @@
}, 50);
}
});
const handlePopState = (event) => {
if (typeof window === "undefined") return;
const statePath =
event?.state && typeof event.state.path === "string"
? event.state.path
: null;
const stateOriginal =
event?.state && typeof event.state.originalPath === "string"
? event.state.originalPath
: null;
if (statePath !== null) {
currentPath = normalizePath(statePath);
} else {
const params = new URLSearchParams(window.location.search);
const paramPath = params.get("path");
currentPath = normalizePath(paramPath || "");
}
if (stateOriginal !== null) {
currentOriginalPath = normalizePath(stateOriginal);
} else {
currentOriginalPath = resolveOriginalPathForDisplay(
currentPath,
currentOriginalPath,
);
}
selectedItems = new Set();
activeMenu = null;
const handlePopState = () => {
syncFromLocation();
};
const handleLocationChange = () => {
syncFromLocation();
};
if (typeof window !== "undefined") {
const originalPushState = window.history.pushState;
const originalReplaceState = window.history.replaceState;
const triggerChange = () => {
window.dispatchEvent(new Event("locationchange"));
};
window.history.pushState = function (...args) {
originalPushState.apply(this, args);
triggerChange();
};
window.history.replaceState = function (...args) {
originalReplaceState.apply(this, args);
triggerChange();
};
window.addEventListener("locationchange", handleLocationChange);
window.addEventListener("popstate", handlePopState);
unpatchHistory = () => {
window.history.pushState = originalPushState;
window.history.replaceState = originalReplaceState;
window.removeEventListener("locationchange", handleLocationChange);
window.removeEventListener("popstate", handlePopState);
};
}
ws.onmessage = async (event) => {
try {
const msg = JSON.parse(event.data);
@@ -1949,6 +1988,7 @@
window.removeEventListener("click", handleClickOutside);
window.removeEventListener("popstate", handlePopState);
if (unpatchHistory) unpatchHistory();
// Resize observer'ı temizle
if (breadcrumbContainer) {