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.
This commit is contained in:
2026-01-31 10:36:07 +03:00
parent 5e6da2b445
commit 569a7975de

View File

@@ -1,5 +1,5 @@
<script> <script>
import { onMount, tick } from "svelte"; import { onDestroy, onMount, tick } from "svelte";
import MatchModal from "../components/MatchModal.svelte"; import MatchModal from "../components/MatchModal.svelte";
import { API, apiFetch, moveEntry, renameFolder, copyEntry } from "../utils/api.js"; import { API, apiFetch, moveEntry, renameFolder, copyEntry } from "../utils/api.js";
import { cleanFileName, extractTitleAndYear } from "../utils/filename.js"; import { cleanFileName, extractTitleAndYear } from "../utils/filename.js";
@@ -452,6 +452,7 @@
const VIEW_KEY = "filesViewMode"; const VIEW_KEY = "filesViewMode";
let viewMode = "grid"; let viewMode = "grid";
let initialPath = ""; let initialPath = "";
let unpatchHistory = null;
if (typeof window !== "undefined") { if (typeof window !== "undefined") {
const storedView = window.localStorage.getItem(VIEW_KEY); const storedView = window.localStorage.getItem(VIEW_KEY);
if (storedView === "grid" || storedView === "list") { if (storedView === "grid" || storedView === "list") {
@@ -491,14 +492,16 @@
let clipboardItem = null; let clipboardItem = null;
let clipboardOperation = null; // 'cut' veya 'copy' 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 params = new URLSearchParams(window.location.search);
const pathParam = params.get("path"); const pathParam = params.get("path");
let nextPath = "";
if (pathParam) { if (pathParam) {
try { try {
initialPath = normalizePath(decodeURIComponent(pathParam)); nextPath = normalizePath(decodeURIComponent(pathParam));
} catch (err) { } catch (err) {
initialPath = normalizePath(pathParam); nextPath = normalizePath(pathParam);
} }
} }
const playParam = params.get("play"); const playParam = params.get("play");
@@ -509,16 +512,49 @@
pendingPlayTarget = playParam; pendingPlayTarget = playParam;
} }
params.delete("play"); params.delete("play");
}
const search = params.toString(); const search = params.toString();
const newUrl = `${window.location.pathname}${search ? `?${search}` : ""}${window.location.hash}`; const newUrl = `${window.location.pathname}${search ? `?${search}` : ""}${window.location.hash}`;
window.history.replaceState( window.history.replaceState(
{ path: initialPath, originalPath: null }, { path: nextPath, originalPath: null },
"", "",
newUrl, newUrl,
); );
} }
currentPath = normalizePath(initialPath);
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;
}
// 🎬 Player kontrolleri // 🎬 Player kontrolleri
let videoEl; let videoEl;
let isPlaying = false; let isPlaying = false;
@@ -1694,34 +1730,37 @@
}, 50); }, 50);
} }
}); });
const handlePopState = (event) => { const handlePopState = () => {
if (typeof window === "undefined") return; syncFromLocation();
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 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) => { ws.onmessage = async (event) => {
try { try {
const msg = JSON.parse(event.data); const msg = JSON.parse(event.data);
@@ -1949,6 +1988,7 @@
window.removeEventListener("click", handleClickOutside); window.removeEventListener("click", handleClickOutside);
window.removeEventListener("popstate", handlePopState); window.removeEventListener("popstate", handlePopState);
if (unpatchHistory) unpatchHistory();
// Resize observer'ı temizle // Resize observer'ı temizle
if (breadcrumbContainer) { if (breadcrumbContainer) {