feat: vault DIR — exclusions par vault et lecture seule déclarable (vault Spark)
This commit is contained in:
+29
-18
@@ -209,6 +209,17 @@ function _openSecretsMenu(x, y) {
|
||||
}, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vault déclaré en lecture seule (DIR_N_READONLY, champ « readonly » de
|
||||
* /api/vaults) : ses menus et boutons d'action ne doivent proposer aucune
|
||||
* mutation (renommer, déplacer, supprimer…) — le backend les refuse en
|
||||
* 403 de toute façon, l'UI le dit avant le clic.
|
||||
*/
|
||||
function vaultIsReadonly(vaultName) {
|
||||
const v = (state.allVaults || []).find((x) => x.name === vaultName);
|
||||
return !!(v && v.readonly);
|
||||
}
|
||||
|
||||
/** Fichier partagé (créé ou reçu) → icône share-2 bleue, sinon icône usuelle. */
|
||||
function sharedFileIconSync(sharedPaths, itemName, vaultName, itemPath) {
|
||||
if (sharedPaths && sharedPaths.has(`${vaultName}::${itemPath}`)) return _sharedIcon();
|
||||
@@ -356,11 +367,11 @@ async function refreshSidebarForContext() {
|
||||
|
||||
vaultItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
const isReadonly = false;
|
||||
const isReadonly = vaultIsReadonly(v.name);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly);
|
||||
});
|
||||
attachTreeItemActionButton(vaultItem, v.name, "", "vault", false);
|
||||
attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false }));
|
||||
attachTreeItemActionButton(vaultItem, v.name, "", "vault", vaultIsReadonly(v.name));
|
||||
attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: vaultIsReadonly(v.name) }));
|
||||
|
||||
container.appendChild(vaultItem);
|
||||
|
||||
@@ -460,11 +471,11 @@ async function loadVaults() {
|
||||
|
||||
vaultItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
const isReadonly = false;
|
||||
const isReadonly = vaultIsReadonly(v.name);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, v.name, '', 'vault', isReadonly);
|
||||
});
|
||||
attachTreeItemActionButton(vaultItem, v.name, "", "vault", false);
|
||||
attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: false }));
|
||||
attachTreeItemActionButton(vaultItem, v.name, "", "vault", vaultIsReadonly(v.name));
|
||||
attachTreeItemLongPress(vaultItem, () => ({ vault: v.name, path: "", type: "vault", isReadonly: vaultIsReadonly(v.name) }));
|
||||
|
||||
container.appendChild(vaultItem);
|
||||
|
||||
@@ -596,8 +607,8 @@ async function incrementalLoadDirectory(vaultName, dirPath, container) {
|
||||
// New item — create it
|
||||
if (item.type === "directory") {
|
||||
const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path, "data-type": "directory" }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]);
|
||||
attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false);
|
||||
attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false }));
|
||||
attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", vaultIsReadonly(vaultName));
|
||||
attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: vaultIsReadonly(vaultName) }));
|
||||
fragment.appendChild(dirItem);
|
||||
|
||||
const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` });
|
||||
@@ -624,14 +635,14 @@ async function incrementalLoadDirectory(vaultName, dirPath, container) {
|
||||
|
||||
dirItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "directory", false);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "directory", vaultIsReadonly(vaultName));
|
||||
});
|
||||
} else {
|
||||
const fileIconName = getFileIcon(item.name);
|
||||
const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name;
|
||||
const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path, "data-type": "file" }, [sharedFileIconSync(sharedPaths, item.name, vaultName, item.path), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]);
|
||||
attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false);
|
||||
attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false }));
|
||||
attachTreeItemActionButton(fileItem, vaultName, item.path, "file", vaultIsReadonly(vaultName));
|
||||
attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: vaultIsReadonly(vaultName) }));
|
||||
fileItem.addEventListener("click", () => {
|
||||
scrollTreeItemIntoView(fileItem, false);
|
||||
if (window.innerWidth <= 768) {
|
||||
@@ -649,7 +660,7 @@ async function incrementalLoadDirectory(vaultName, dirPath, container) {
|
||||
|
||||
fileItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "file", false);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, "file", vaultIsReadonly(vaultName));
|
||||
});
|
||||
|
||||
fragment.appendChild(fileItem);
|
||||
@@ -944,8 +955,8 @@ async function loadDirectory(vaultName, dirPath, container) {
|
||||
|
||||
if (item.type === "directory") {
|
||||
const dirItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path, "data-type": "directory" }, [icon("chevron-right", 14), icon("folder", 16), el("span", { class: "tree-item-text" }, [document.createTextNode(item.name)]), smallBadge(item.children_count)]);
|
||||
attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", false);
|
||||
attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: false }));
|
||||
attachTreeItemActionButton(dirItem, vaultName, item.path, "directory", vaultIsReadonly(vaultName));
|
||||
attachTreeItemLongPress(dirItem, () => ({ vault: vaultName, path: item.path, type: "directory", isReadonly: vaultIsReadonly(vaultName) }));
|
||||
fragment.appendChild(dirItem);
|
||||
|
||||
const subContainer = el("div", { class: "tree-children collapsed", id: `dir-${vaultName}-${item.path}` });
|
||||
@@ -972,7 +983,7 @@ async function loadDirectory(vaultName, dirPath, container) {
|
||||
|
||||
dirItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
const isReadonly = false;
|
||||
const isReadonly = vaultIsReadonly(vaultName);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'directory', isReadonly);
|
||||
});
|
||||
} else {
|
||||
@@ -980,8 +991,8 @@ async function loadDirectory(vaultName, dirPath, container) {
|
||||
const displayName = item.name.match(/\.md$/i) ? item.name.replace(/\.md$/i, "") : item.name;
|
||||
const isShared = sharedPaths.has(`${vaultName}::${item.path}`);
|
||||
const fileItem = el("div", { class: "tree-item", "data-vault": vaultName, "data-path": item.path, "data-type": "file" }, [isShared ? _sharedIcon() : icon(fileIconName, 16), el("span", { class: "tree-item-text" }, [document.createTextNode(displayName)])]);
|
||||
attachTreeItemActionButton(fileItem, vaultName, item.path, "file", false);
|
||||
attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: false }));
|
||||
attachTreeItemActionButton(fileItem, vaultName, item.path, "file", vaultIsReadonly(vaultName));
|
||||
attachTreeItemLongPress(fileItem, () => ({ vault: vaultName, path: item.path, type: "file", isReadonly: vaultIsReadonly(vaultName) }));
|
||||
fileItem.addEventListener("click", () => {
|
||||
scrollTreeItemIntoView(fileItem, false);
|
||||
if (window.innerWidth <= 768) {
|
||||
@@ -999,7 +1010,7 @@ async function loadDirectory(vaultName, dirPath, container) {
|
||||
|
||||
fileItem.addEventListener("contextmenu", (e) => {
|
||||
e.preventDefault();
|
||||
const isReadonly = false;
|
||||
const isReadonly = vaultIsReadonly(vaultName);
|
||||
ContextMenuManager.show(e.clientX, e.clientY, vaultName, item.path, 'file', isReadonly);
|
||||
});
|
||||
|
||||
|
||||
Reference in New Issue
Block a user