mirror of
https://github.com/LisherSong/ps5-web-file-manager.git
synced 2026-10-06 21:00:26 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
48d669b848 | ||
|
|
dafbd8dcbf |
No files matched your search
@@ -13,7 +13,7 @@ ifeq ($(MAKECMDGOALS),)
|
||||
endif
|
||||
endif
|
||||
|
||||
VERSION_TAG := v1.3
|
||||
VERSION_TAG := v1.4
|
||||
TITLE_ID := FMGR88888
|
||||
PYTHON ?= python3
|
||||
STRIP ?= $(PS5_PAYLOAD_SDK)/bin/prospero-strip
|
||||
|
||||
+4
-2
@@ -65,13 +65,13 @@ body {
|
||||
}
|
||||
|
||||
.top-left {
|
||||
flex: 1 1 420px;
|
||||
flex: 1 1 0;
|
||||
min-width: 0;
|
||||
margin-top: 15px;
|
||||
}
|
||||
|
||||
.top-right {
|
||||
flex: 1 1 360px;
|
||||
flex: 0 1 auto;
|
||||
min-width: 0;
|
||||
margin-left: auto;
|
||||
justify-content: flex-end;
|
||||
@@ -88,6 +88,7 @@ body {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
text-align: left;
|
||||
flex: 1 1 auto;
|
||||
min-width: 0;
|
||||
}
|
||||
@@ -110,6 +111,7 @@ body {
|
||||
}
|
||||
|
||||
.space-item {
|
||||
flex: 0 0 auto;
|
||||
margin-left: 14px;
|
||||
max-width: 100%;
|
||||
overflow: hidden;
|
||||
|
||||
+104
-9
@@ -29,7 +29,7 @@ let downloadFrame = null;
|
||||
let uploadXhr = null;
|
||||
let L = {};
|
||||
|
||||
const APP_VERSION = "v1.3";
|
||||
const APP_VERSION = "v1.4";
|
||||
const LAST_PATH_KEY = "ps5-web-file-mgr:last-path";
|
||||
const SORT_KEY = "ps5-web-file-mgr:list-sort";
|
||||
const LOADING_DISPLAY_DELAY = 250;
|
||||
@@ -316,6 +316,23 @@ function displayPath(path) {
|
||||
return decodeFsText(path);
|
||||
}
|
||||
|
||||
function renderAddressPath() {
|
||||
const path = displayPath(cwd);
|
||||
pathEl.title = path;
|
||||
pathEl.textContent = path;
|
||||
if (pathEl.scrollWidth <= pathEl.clientWidth) return;
|
||||
|
||||
let low = 0;
|
||||
let high = path.length;
|
||||
while (low < high) {
|
||||
const count = Math.ceil((low + high) / 2);
|
||||
pathEl.textContent = "..." + path.slice(-count);
|
||||
if (pathEl.scrollWidth <= pathEl.clientWidth) low = count;
|
||||
else high = count - 1;
|
||||
}
|
||||
pathEl.textContent = "..." + path.slice(-low);
|
||||
}
|
||||
|
||||
async function fetchText(path, params) {
|
||||
const response = await request(path, params, { method: "GET" });
|
||||
return {
|
||||
@@ -498,6 +515,54 @@ function readSavedPath() {
|
||||
}
|
||||
}
|
||||
|
||||
function historyPath() {
|
||||
const hash = window.location.hash || "";
|
||||
if (hash.length <= 1) return "";
|
||||
try {
|
||||
const path = decodeURIComponent(hash.slice(1));
|
||||
return path.charAt(0) === "/" ? path : "";
|
||||
} catch (err) {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
function writeHistoryPath(path, replace) {
|
||||
if (!window.history || !history.pushState) return;
|
||||
const hash = "#" + encodeURIComponent(path || "/");
|
||||
if (window.location.hash === hash) return;
|
||||
const state = { path: path || "/" };
|
||||
if (replace && history.replaceState) history.replaceState(state, "", hash);
|
||||
else history.pushState(state, "", hash);
|
||||
}
|
||||
|
||||
function pathHistoryChain(path) {
|
||||
const clean = String(path || "/").replace(/\/+$/, "") || "/";
|
||||
const parts = clean.split("/");
|
||||
const chain = ["/"];
|
||||
let current = "";
|
||||
for (let i = 1; i < parts.length; i++) {
|
||||
if (!parts[i]) continue;
|
||||
current += "/" + parts[i];
|
||||
chain.push(current);
|
||||
}
|
||||
return chain;
|
||||
}
|
||||
|
||||
function seedHistoryPath(path) {
|
||||
if (!window.history || !history.pushState || !history.replaceState) return;
|
||||
const chain = pathHistoryChain(path);
|
||||
for (let i = 0; i < chain.length; i++) {
|
||||
writeHistoryPath(chain[i], i === 0);
|
||||
}
|
||||
}
|
||||
|
||||
function historyBlocked() {
|
||||
return Boolean(busy || loadingPath || pendingAbortController ||
|
||||
pendingOverlayText || taskOverlayTimer || !overlayEl.hidden ||
|
||||
!contentLoadingEl.hidden || contentEl.classList.contains("loading") ||
|
||||
!textEditorOverlayEl.hidden || !imagePreviewOverlayEl.hidden);
|
||||
}
|
||||
|
||||
function savePath(path) {
|
||||
try {
|
||||
localStorage.setItem(LAST_PATH_KEY, path || "/");
|
||||
@@ -547,8 +612,10 @@ async function refreshSpaces() {
|
||||
span.title = item.path + " " + span.textContent;
|
||||
spaceInfoEl.appendChild(span);
|
||||
}
|
||||
renderAddressPath();
|
||||
} catch (err) {
|
||||
spaceInfoEl.textContent = "";
|
||||
renderAddressPath();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1143,7 +1210,11 @@ function actionParentDirectory(event) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
if (busy || loadingPath || cwd === "/") return;
|
||||
load(parentPath(cwd), undefined, false, true);
|
||||
if (window.history && history.back && historyPath() === cwd) {
|
||||
history.back();
|
||||
} else {
|
||||
load(parentPath(cwd), undefined, false, true, "push");
|
||||
}
|
||||
}
|
||||
|
||||
function cell(text) {
|
||||
@@ -1159,7 +1230,7 @@ function classCell(className, text) {
|
||||
return td;
|
||||
}
|
||||
|
||||
async function load(path, scrollTop, force, alertOnError) {
|
||||
async function load(path, scrollTop, force, alertOnError, historyMode) {
|
||||
const shouldScrollTop = scrollTop !== false;
|
||||
if ((busy && !force) || loadingPath) return;
|
||||
loadingPath = path;
|
||||
@@ -1172,8 +1243,9 @@ async function load(path, scrollTop, force, alertOnError) {
|
||||
}
|
||||
if (!contentLoadingEl.hidden) await nextPaint();
|
||||
cwd = data.path;
|
||||
pathEl.textContent = displayPath(cwd);
|
||||
renderAddressPath();
|
||||
savePath(cwd);
|
||||
if (historyMode) writeHistoryPath(cwd, historyMode === "replace");
|
||||
refreshSpaces();
|
||||
entries = data.entries.sort(compareEntries);
|
||||
selected.clear();
|
||||
@@ -1192,6 +1264,12 @@ async function load(path, scrollTop, force, alertOnError) {
|
||||
}
|
||||
}
|
||||
|
||||
async function loadAndReveal(path, scrollTop, force, alertOnError, historyMode, revealPath) {
|
||||
const ok = await load(path, scrollTop, force, alertOnError, historyMode);
|
||||
if (ok && revealPath) revealPathInList(revealPath);
|
||||
return ok;
|
||||
}
|
||||
|
||||
async function runAction(label, fn, options) {
|
||||
try {
|
||||
taskRefreshPath = cwd;
|
||||
@@ -1820,6 +1898,19 @@ textEditorCloseBtn.addEventListener("click", requestCloseTextEditor);
|
||||
textEditorSaveBtn.addEventListener("click", saveTextEditor);
|
||||
newTextBtn.addEventListener("click", actionNewText);
|
||||
imagePreviewCloseBtn.addEventListener("click", closeImagePreview);
|
||||
window.addEventListener("resize", renderAddressPath);
|
||||
window.addEventListener("popstate", event => {
|
||||
if (historyBlocked()) {
|
||||
writeHistoryPath(cwd, false);
|
||||
setStatus(t("activeTask"));
|
||||
return;
|
||||
}
|
||||
const path = event.state && event.state.path ? event.state.path : historyPath();
|
||||
if (path && path !== cwd) {
|
||||
const revealPath = parentPath(cwd) === path ? cwd : "";
|
||||
loadAndReveal(path, false, false, true, null, revealPath);
|
||||
}
|
||||
});
|
||||
document.addEventListener("click", event => {
|
||||
if (!uploadMenuEl || uploadMenuEl.contains(event.target)) return;
|
||||
uploadMenuEl.classList.remove("open");
|
||||
@@ -1874,8 +1965,8 @@ filesEl.addEventListener("click", event => {
|
||||
if (item.type === "parent" || item.type === "d") {
|
||||
const revealPath = item.type === "parent" ? cwd : "";
|
||||
setTimeout(async () => {
|
||||
if (await load(item.path, item.type === "parent" ? false : undefined, false, true)) {
|
||||
/* if (revealPath) revealPathInList(revealPath); */
|
||||
if (await load(item.path, item.type === "parent" ? false : undefined, false, true, "push")) {
|
||||
if (revealPath) revealPathInList(revealPath);
|
||||
} else await load(cwd, false, true);
|
||||
}, 0);
|
||||
}
|
||||
@@ -1918,9 +2009,9 @@ async function init() {
|
||||
applyStaticText();
|
||||
readSavedSort();
|
||||
updateSortHeaders();
|
||||
const savedPath = readSavedPath();
|
||||
const savedPath = historyPath() || readSavedPath();
|
||||
cwd = savedPath;
|
||||
pathEl.textContent = displayPath(cwd);
|
||||
renderAddressPath();
|
||||
taskRefreshPath = savedPath;
|
||||
refreshSpaces();
|
||||
await pollTasks();
|
||||
@@ -1928,7 +2019,11 @@ async function init() {
|
||||
setStatus(t("activeTask"));
|
||||
return;
|
||||
}
|
||||
if (!(await load(savedPath || "/")) && savedPath !== "/") await load("/");
|
||||
if (await load(savedPath || "/", undefined, false, false)) {
|
||||
seedHistoryPath(cwd);
|
||||
} else if (savedPath !== "/" && await load("/", undefined, false, false)) {
|
||||
seedHistoryPath(cwd);
|
||||
}
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
Reference in new issue
Block a user