Add folder move functionality and update context menu

This commit is contained in:
2026-02-01 01:06:42 +01:00
parent 58184c0f51
commit bc68d4b661

View File

@@ -25,6 +25,7 @@ import {
listFolders, listFolders,
listTexts, listTexts,
listVersions, listVersions,
moveFolder,
moveTextToFolder, moveTextToFolder,
saveManualVersion, saveManualVersion,
searchTexts, searchTexts,
@@ -707,6 +708,18 @@ export default function App() {
.sort((a, b) => a.label.localeCompare(b.label)); .sort((a, b) => a.label.localeCompare(b.label));
}, [buildFolderPath, folders]); }, [buildFolderPath, folders]);
const isDescendantFolder = useCallback(
(folderId: string, potentialAncestorId: string) => {
let current: string | null = folderById.get(folderId)?.parent_id ?? null;
while (current) {
if (current === potentialAncestorId) return true;
current = folderById.get(current)?.parent_id ?? null;
}
return false;
},
[folderById]
);
const handleMoveTextToFolder = useCallback( const handleMoveTextToFolder = useCallback(
async (textId: string, folderId: string | null) => { async (textId: string, folderId: string | null) => {
await moveTextToFolder(textId, folderId, null); await moveTextToFolder(textId, folderId, null);
@@ -715,6 +728,21 @@ export default function App() {
[refreshTexts] [refreshTexts]
); );
const handleMoveFolderToFolder = useCallback(
async (folderId: string, parentId: string | null) => {
await moveFolder(folderId, parentId, null);
await refreshFolders();
if (parentId) {
setExpandedFolders((prev) => {
const next = new Set(prev);
next.add(parentId);
return next;
});
}
},
[refreshFolders]
);
const handleDeleteText = useCallback( const handleDeleteText = useCallback(
async (promptId: string) => { async (promptId: string) => {
await deleteText(promptId); await deleteText(promptId);
@@ -797,6 +825,30 @@ export default function App() {
const handleFolderContextMenu = useCallback( const handleFolderContextMenu = useCallback(
async (event: React.MouseEvent, folder: Folder) => { async (event: React.MouseEvent, folder: Folder) => {
event.preventDefault(); event.preventDefault();
const moveTargets = [
{
text: "Top level",
action: () => {
handleMoveFolderToFolder(folder.id, null).catch((error) => {
console.error("Failed to move folder", error);
});
}
},
...folderPathList
.filter(
(candidate) =>
candidate.id !== folder.id &&
!isDescendantFolder(candidate.id, folder.id)
)
.map((candidate) => ({
text: candidate.label,
action: () => {
handleMoveFolderToFolder(folder.id, candidate.id).catch((error) => {
console.error("Failed to move folder", error);
});
}
}))
];
const menu = await Menu.new({ const menu = await Menu.new({
items: [ items: [
{ {
@@ -814,12 +866,16 @@ export default function App() {
onConfirm: () => handleDeleteFolder(folder.id) onConfirm: () => handleDeleteFolder(folder.id)
}); });
} }
},
{
text: "Move to folder",
items: moveTargets
} }
] ]
}); });
await menu.popup(undefined, getCurrentWindow()); await menu.popup(undefined, getCurrentWindow());
}, },
[handleDeleteFolder, startEditingFolder] [folderPathList, handleDeleteFolder, handleMoveFolderToFolder, isDescendantFolder, startEditingFolder]
); );
const createTextFromFile = useCallback( const createTextFromFile = useCallback(