MCPcopy Create free account
hub / github.com/ZenNotes/zennotes / AssetsView

Function AssetsView

packages/app-core/src/components/AssetsView.tsx:49–238  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

47 * (images, PDFs, attachments), independent of the notes tree.
48 */
49export function AssetsView(): JSX.Element {
50 const assetFiles = useStore((s) => s.assetFiles)
51 const openNoteInTab = useStore((s) => s.openNoteInTab)
52 const deleteAsset = useStore((s) => s.deleteAsset)
53 const refreshAssets = useStore((s) => s.refreshAssets)
54 const notes = useStore((s) => s.notes)
55 const vaultRoot = useStore((s) => s.vault?.root ?? null)
56 const [filter, setFilter] = useState('')
57 const [menu, setMenu] = useState<{ x: number; y: number; asset: AssetMeta } | null>(null)
58
59 const assets = useMemo(() => {
60 const q = filter.trim().toLowerCase()
61 const matched = q
62 ? assetFiles.filter((a) => a.name.toLowerCase().includes(q) || a.path.toLowerCase().includes(q))
63 : assetFiles
64 return [...matched].sort((a, b) => naturalCompare(a.name, b.name))
65 }, [assetFiles, filter])
66
67 // assetPath → note paths that embed it (resolved via relative-path + the
68 // unique-basename fallback, matching how embeds render). (#185)
69 const usage = useMemo(() => {
70 const map = new Map<string, string[]>()
71 for (const note of notes) {
72 for (const href of note.assetEmbeds ?? []) {
73 const resolved = resolveAssetVaultRelativePath(vaultRoot, note.path, href)
74 if (!resolved) continue
75 const arr = map.get(resolved)
76 if (arr) {
77 if (!arr.includes(note.path)) arr.push(note.path)
78 } else {
79 map.set(resolved, [note.path])
80 }
81 }
82 }
83 return map
84 }, [notes, vaultRoot, assetFiles])
85
86 const copyEmbed = (asset: AssetMeta): void => {
87 void navigator.clipboard?.writeText(`![[${asset.name}]]`)
88 }
89
90 const renameAsset = async (asset: AssetMeta): Promise<void> => {
91 if (typeof window.zen.renameAsset !== 'function') return
92 const ext = asset.name.includes('.') ? asset.name.slice(asset.name.lastIndexOf('.')) : ''
93 const base = ext ? asset.name.slice(0, -ext.length) : asset.name
94 const next = await promptApp({
95 title: 'Rename asset',
96 initialValue: base,
97 okLabel: 'Rename',
98 validate: (v) => (v.includes('/') ? 'Use only a name' : null)
99 })
100 if (!next) return
101 const clean = next.trim()
102 if (!clean || `${clean}${ext}` === asset.name) return
103 try {
104 await window.zen.renameAsset(asset.path, `${clean}${ext}`)
105 await refreshAssets()
106 } catch (err) {

Callers

nothing calls this directly

Calls 8

naturalCompareFunction · 0.90
confirmMoveToTrashFunction · 0.90
menuItemsFunction · 0.85
openFunction · 0.70
formatBytesFunction · 0.70
formatDateFunction · 0.70
deleteAssetFunction · 0.50

Tested by

no test coverage detected