import { ArrowLeft, Download, Edit2, Expand, FileText, Folder, FolderPlus, Glasses, MoreHorizontal, Minimize2, PencilLine, Plus, Search, Upload, X, } from "lucide-react"; import React, { lazy, Suspense, useCallback, useEffect, useMemo, useRef, useState } from "react"; import { useI18n } from "../../application/i18n/I18nProvider"; import { useApplicationBackend } from "../../application/state/useApplicationBackend"; import { useStoredNumber } from "../../application/state/useStoredNumber"; import { useStoredString } from "../../application/state/useStoredString"; import { ancestorNoteGroupPaths, buildVaultNoteMarkdownExportFiles, cleanNoteGroupPath, getNoteGroupParentPath, isNoteGroupInside, joinNoteGroupPath, matchesVaultNoteSearch, importMarkdownPayloadsToVaultNotes, normalizeNoteGroups, normalizeVaultNotes, remapExpandedNoteGroupPaths, replaceNoteGroupPrefix, resolveMovedNoteGroupPath, sanitizeNoteExportFileNamePart, type VaultNotesExportScope, } from "../../domain/notes"; import { getNextVaultOrder, reorderVaultItems, reorderVaultStrings, sortByVaultOrder } from "../../domain/vaultOrder"; import { STORAGE_KEY_VAULT_NOTES_EDITOR_MODE, STORAGE_KEY_VAULT_NOTES_TREE_WIDTH, } from "../../infrastructure/config/storageKeys"; import { logger } from "../../lib/logger"; import { cn } from "../../lib/utils"; import { readTextFile } from "../../lib/readTextFile"; import { buildTextFilesZipBlob } from "../../lib/textZip"; import type { Host, VaultNote } from "../../types"; import { Button } from "../ui/button"; import { LazyLoadBoundary } from "../ui/lazy-load-boundary"; import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, } from "../ui/context-menu"; import { Dropdown, DropdownContent, DropdownTrigger } from "../ui/dropdown"; import { Input } from "../ui/input"; import { ScrollArea } from "../ui/scroll-area"; import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; import { toast } from "../ui/toast"; import { VaultTreeGroupRow, VaultTreeInlineRenameInput, VaultTreeItemRow, } from "../vault/VaultTreeRow"; import { VaultDeleteConfirmDialog } from "../vault/VaultDeleteConfirmDialog"; import { clearVaultDropIndicator, getVaultDropIntent, getVaultDropPosition, type VaultDropPosition, hasVaultDragType, markVaultDropIndicator, markVaultInsideDropIndicator, } from "../vault/vaultReorderDrag"; import type { NoteEditorMode } from "./InlineMarkdownEditor"; const InlineMarkdownEditor = lazy(() => import("./InlineMarkdownEditor").then((module) => ({ default: module.InlineMarkdownEditor })), ); interface NoteFolderNode { name: string; path: string; children: NoteFolderNode[]; notes: VaultNote[]; } type NotesToolbarPanel = "search" | null; const toolbarIconButtonClass = "netcatty-tab h-7 w-7 shrink-0 rounded-md p-0 hover:bg-transparent"; const menuItemClass = "flex h-8 w-full items-center rounded-md px-3 text-left text-sm hover:bg-secondary"; const NOTES_TREE_DEFAULT_WIDTH = 300; const NOTES_TREE_MIN_WIDTH = 220; const NOTES_TREE_MAX_WIDTH = 520; const NOTE_DRAG_TYPE = "application/x-netcatty-note-id"; const NOTE_GROUP_DRAG_TYPE = "application/x-netcatty-note-group-path"; export const normalizeNoteEditorMode = (value: string | null): NoteEditorMode | null => value === "edit" || value === "preview" ? value : null; const isNoteEditorMode = (value: string | null): value is NoteEditorMode => normalizeNoteEditorMode(value) !== null; const InlineMarkdownEditorFallback = () => (