Fix mobile open file list behavior for deleted and long-named files (#1391)

* Fix mobile open file list cleanup and long names

- Remove deleted files from persisted open file tabs
- Invalidate cached file content when stat/delete/rename affects paths
- Keep mobile open-file close buttons visible for long filenames
- Add marquee scrolling for overflowing file names

* Fix bot comments

---------

Co-authored-by: Konstantin Zolin <zolin_ka@vk.com>
This commit is contained in:
kostazol
2026-05-24 15:49:22 +03:00
committed by GitHub
co-authored by Konstantin Zolin
parent c5862cc6ee
commit af25edd3f7
3 changed files with 156 additions and 19 deletions
+24 -12
View File
@@ -13,6 +13,20 @@ import {
function withContentCache(files: FilesAPI): FilesAPI {
const cache = new Map<string, { content: string; path: string; size?: number; mtimeMs?: number }>();
const removeCacheEntry = (path: string) => {
cache.delete(path);
removeContentBytes(path);
};
const removeCacheEntriesByPrefix = (path: string) => {
const prefix = path.endsWith('/') ? path : `${path}/`;
for (const key of cache.keys()) {
if (key === path || key.startsWith(prefix)) {
removeCacheEntry(key);
}
}
};
/** Whether cached metadata still matches the file on disk. */
const statMatches = (
cached: { size?: number; mtimeMs?: number },
@@ -86,10 +100,12 @@ function withContentCache(files: FilesAPI): FilesAPI {
if (hit) {
// Validate cached entry is still fresh
if (files.statFile) {
const latest = await files.statFile(path).catch(() => null);
if (latest && !statMatches(hit, latest)) {
cache.delete(path);
removeContentBytes(path);
const latest = await files.statFile(path).catch(() => {
removeCacheEntry(path);
return null;
});
if (!latest || !statMatches(hit, latest)) {
removeCacheEntry(path);
return readFreshFile(path);
}
}
@@ -104,26 +120,22 @@ function withContentCache(files: FilesAPI): FilesAPI {
// Invalidate cache on writes, deletes, renames
const cachedWriteFile: FilesAPI['writeFile'] = files.writeFile
? async (path, content) => {
cache.delete(path);
removeContentBytes(path);
removeCacheEntry(path);
return files.writeFile!(path, content);
}
: undefined;
const cachedDelete: FilesAPI['delete'] = files.delete
? async (path) => {
cache.delete(path);
removeContentBytes(path);
removeCacheEntriesByPrefix(path);
return files.delete!(path);
}
: undefined;
const cachedRename: FilesAPI['rename'] = files.rename
? async (oldPath, newPath) => {
cache.delete(oldPath);
removeContentBytes(oldPath);
cache.delete(newPath);
removeContentBytes(newPath);
removeCacheEntriesByPrefix(oldPath);
removeCacheEntriesByPrefix(newPath);
return files.rename!(oldPath, newPath);
}
: undefined;