List Files through get, because query cannot see a folder before 0.16

Creating a folder on the live 0.15.5 server did nothing visible, with no error
and nothing after a reload. The folder was real all along: FileNode/query masks
its results with document_ids(false) — resources that are *not* containers — so
it returns files and never folders, and says nothing about the omission.

FileNode/get carries no such mask, so on those servers the whole tree comes
from a single get with ids:null instead. That also stops ensureFolder making a
fresh "ihasmail" folder on every signature save, having never been able to find
the one already there.
This commit is contained in:
2026-08-24 10:05:08 -07:00
parent b8263aa785
commit 57ff18bb7f
4 changed files with 73 additions and 28 deletions
+21 -14
View File
@@ -6,7 +6,7 @@
*/
import { CAP, client, setErrorMessage } from "@/jmap/client";
import type { FileNode, GetResponse, QueryResponse, SetResponse } from "@/jmap/types";
import { directoryCreate, fileCreate, supportsNodeType, normalizeFileNodes } from "@/lib/filenode";
import { directoryCreate, fileCreate, normalizeFileNodes, queryOmitsDirectories, supportsNodeType } from "@/lib/filenode";
import { useSession } from "@/store/session";
import { toast } from "@/ui/toast";
@@ -17,19 +17,26 @@ const folderProps = () => (supportsNodeType() ? ["id", "name", "nodeType", "pare
async function ensureFolder(accountId: string): Promise<string> {
let list: FileNode[] = [];
try {
const res = await client.chain([
["FileNode/query", { accountId, filter: { isTopLevel: true, nodeType: "directory", name: FOLDER }, limit: 5 }, "q"],
["FileNode/get", { accountId, "#ids": { resultOf: "q", name: "FileNode/query", path: "/ids" }, properties: folderProps() }, "g"],
]);
list = normalizeFileNodes((res.get("g")?.[0] as unknown as GetResponse<FileNode>).list);
} catch {
// Older servers: no filter support — scan everything.
const res = await client.chain([
["FileNode/query", { accountId, limit: 1000 }, "q"],
["FileNode/get", { accountId, "#ids": { resultOf: "q", name: "FileNode/query", path: "/ids" }, properties: folderProps() }, "g"],
]);
list = normalizeFileNodes((res.get("g")?.[0] as unknown as GetResponse<FileNode>).list);
if (queryOmitsDirectories()) {
// Query cannot see a directory on these servers, so it would never find the
// folder and we would make a fresh one on every save. Ask get for the lot.
const res = await client.call<GetResponse<FileNode>>("FileNode/get", { accountId, ids: null, properties: folderProps() });
list = normalizeFileNodes(res.list);
} else {
try {
const res = await client.chain([
["FileNode/query", { accountId, filter: { isTopLevel: true, nodeType: "directory", name: FOLDER }, limit: 5 }, "q"],
["FileNode/get", { accountId, "#ids": { resultOf: "q", name: "FileNode/query", path: "/ids" }, properties: folderProps() }, "g"],
]);
list = normalizeFileNodes((res.get("g")?.[0] as unknown as GetResponse<FileNode>).list);
} catch {
// Filters unsupported: scan everything and pick it out here.
const res = await client.chain([
["FileNode/query", { accountId, limit: 1000 }, "q"],
["FileNode/get", { accountId, "#ids": { resultOf: "q", name: "FileNode/query", path: "/ids" }, properties: folderProps() }, "g"],
]);
list = normalizeFileNodes((res.get("g")?.[0] as unknown as GetResponse<FileNode>).list);
}
}
const existing = list.find((n) => n.name === FOLDER && n.nodeType === "directory" && !n.parentId);
if (existing) return existing.id;