143 lines
3.6 KiB
Go
143 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"time"
|
|
|
|
"verstak/internal/core/activity"
|
|
"verstak/internal/core/notes"
|
|
"verstak/internal/core/nodes"
|
|
syncsvc "verstak/internal/core/sync"
|
|
)
|
|
|
|
func (a *App) ListNotes(nodeID string) ([]NodeDTO, error) {
|
|
if err := a.requireVault(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Return empty for non-notes-capable parents.
|
|
if !a.notes.SupportsNotes(nodeID) {
|
|
return []NodeDTO{}, nil
|
|
}
|
|
|
|
// Try the canonical layout: notes live under a "Notes" folder.
|
|
// Also fall back to direct TypeNote children so that notes placed
|
|
// directly by AssignInboxNode / old layout are still visible.
|
|
notesFolder := a.notes.FindNotesFolder(nodeID)
|
|
|
|
// Direct children (old layout / inbox-assigned notes)
|
|
directChildren, err := a.nodes.ListChildren(nodeID, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
seen := map[string]bool{}
|
|
var result []NodeDTO
|
|
processNote := func(n nodes.Node) {
|
|
if n.Type == nodes.TypeNote && !seen[n.ID] {
|
|
seen[n.ID] = true
|
|
result = append(result, toNodeDTO(&n))
|
|
}
|
|
}
|
|
|
|
if notesFolder != nil {
|
|
// Canonical layout: notes inside the Notes folder
|
|
notesChildren, err := a.nodes.ListChildren(notesFolder.ID, false)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
for i := range notesChildren {
|
|
processNote(notesChildren[i])
|
|
}
|
|
}
|
|
|
|
// Also include direct TypeNote children (old / inbox-assigned notes)
|
|
for i := range directChildren {
|
|
processNote(directChildren[i])
|
|
}
|
|
|
|
// Trigger repair in background for old-layout notes
|
|
go func() {
|
|
if _, err := a.notes.RepairNotesLayout(); err != nil {
|
|
// log only
|
|
}
|
|
}()
|
|
|
|
return result, nil
|
|
}
|
|
|
|
func (a *App) RepairNotesLayout() (*notes.RepairResult, error) {
|
|
if err := a.requireVault(); err != nil {
|
|
return nil, err
|
|
}
|
|
return a.notes.RepairNotesLayout()
|
|
}
|
|
|
|
func (a *App) CreateNote(parentID, title string) (*NodeDTO, error) {
|
|
if err := a.requireVault(); err != nil {
|
|
return nil, err
|
|
}
|
|
node, fileRec, err := a.notes.Create(parentID, title, "")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
_ = a.activity.Record(parentID, activity.TargetNote, node.ID, "", activity.TypeNoteCreated, title, "")
|
|
_ = a.sync.RecordOp(syncsvc.EntityNote, node.ID, syncsvc.OpCreate, notePayload(node, fileRec, ""))
|
|
dto := toNodeDTO(node)
|
|
return &dto, nil
|
|
}
|
|
|
|
func (a *App) ReadNote(noteID string) (string, error) {
|
|
if err := a.requireVault(); err != nil {
|
|
return "", err
|
|
}
|
|
return a.notes.Read(noteID)
|
|
}
|
|
|
|
func (a *App) SaveNote(noteID, content string) error {
|
|
if err := a.requireVault(); err != nil {
|
|
return err
|
|
}
|
|
if err := a.notes.Save(noteID, content); err != nil {
|
|
return err
|
|
}
|
|
if n, err := a.nodes.GetActive(noteID); err == nil {
|
|
pid := ""
|
|
if n.ParentID != nil {
|
|
pid = *n.ParentID
|
|
}
|
|
_ = a.activity.Record(pid, activity.TargetNote, noteID, "", activity.TypeNoteUpdated, n.Title, "")
|
|
_ = a.sync.RecordOp(syncsvc.EntityNote, noteID, syncsvc.OpUpdate, map[string]interface{}{
|
|
"node_id": noteID,
|
|
"content": content,
|
|
"updated_at": time.Now().UTC().Format(time.RFC3339),
|
|
})
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (a *App) RenameNote(noteID, newTitle string) error {
|
|
if err := a.requireVault(); err != nil {
|
|
return err
|
|
}
|
|
return a.notes.Rename(noteID, newTitle)
|
|
}
|
|
|
|
func (a *App) DeleteNote(noteID string) error {
|
|
if err := a.requireVault(); err != nil {
|
|
return err
|
|
}
|
|
// Record activity and sync op before delete (need node info).
|
|
n, _ := a.nodes.GetActive(noteID)
|
|
pid := ""
|
|
if n != nil && n.ParentID != nil {
|
|
pid = *n.ParentID
|
|
}
|
|
title := ""
|
|
if n != nil {
|
|
title = n.Title
|
|
}
|
|
_ = a.activity.Record(pid, activity.TargetNote, noteID, "", activity.TypeNoteDeleted, title, "")
|
|
_ = a.sync.RecordOp(syncsvc.EntityNote, noteID, syncsvc.OpDelete, nil)
|
|
return a.notes.Delete(noteID)
|
|
}
|