bindings_nodes: fix parent variable redeclaration (rename to parentVal)

This commit is contained in:
mirivlad 2026-06-03 02:18:10 +08:00
parent a31f5fd702
commit 7e38ffed7b
1 changed files with 370 additions and 205 deletions

View File

@ -228,74 +228,109 @@ func (a *App) RenameNode(nodeID, newTitle string) error {
isFolderLike := n.Type != nodes.TypeNote && n.Type != nodes.TypeFile
if isFolderLike {
// Folder-like node: rename physical directory
if n.FsPath == "" {
return fmt.Errorf("cannot rename node %s (%s): fs_path is empty", n.ID, n.Title)
}
return a.renameFolderNode(nodeID, n, newTitle, seg)
}
return a.renameNoteFileNode(nodeID, n, newTitle, seg)
}
oldFsPath := n.FsPath
oldPhysPath := filepath.Join(a.vault, oldFsPath)
parentFsPath := ""
if n.ParentID != nil {
p, err := a.nodes.GetActive(*n.ParentID)
if err == nil {
parentFsPath = p.FsPath
}
}
newFsPath := seg
if parentFsPath != "" {
newFsPath = filepath.Join(parentFsPath, seg)
}
newPhysPath := filepath.Join(a.vault, newFsPath)
newPhysPath = templates.UniquePath(newPhysPath)
rel, _ := filepath.Rel(a.vault, newPhysPath)
newFsPath = rel
if _, err := syncsvc.SafeVaultPath(a.vault, newFsPath); err != nil {
return fmt.Errorf("path safety: %w", err)
}
oldTitle := n.Title
// Check source exists before filesystem rename
if _, err := os.Stat(oldPhysPath); err != nil {
return fmt.Errorf("source folder not found: %w", err)
}
if err := os.Rename(oldPhysPath, newPhysPath); err != nil {
return fmt.Errorf("rename folder: %w", err)
}
// Update DB only after successful filesystem rename
if err := a.nodes.UpdateTitle(nodeID, newTitle); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
if err := a.nodes.UpdateFsPath(nodeID, newFsPath); err != nil {
_ = a.nodes.UpdateTitle(nodeID, oldTitle)
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
if err := a.nodes.UpdateFsPathRecursive(nodeID, newFsPath); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
pid := ""
if n.ParentID != nil {
pid = *n.ParentID
}
_ = a.activity.Record(pid, activity.TargetFolder, nodeID, "", activity.TypeFolderRenamed, newTitle, `{"from":"`+oldTitle+`","to":"`+newTitle+`"}`)
_ = a.sync.RecordOp(syncsvc.EntityFolder, nodeID, syncsvc.OpUpdate, map[string]interface{}{
"title": newTitle,
"fs_path": newFsPath,
"updated_at": time.Now().UTC().Format(time.RFC3339),
})
return nil
// renameFolderNode renames a folder-like node atomically: FS first, then DB transaction.
func (a *App) renameFolderNode(nodeID string, n *nodes.Node, newTitle, seg string) error {
if n.FsPath == "" {
return fmt.Errorf("cannot rename node %s (%s): fs_path is empty", n.ID, n.Title)
}
// Note/file node: rename the physical file, update file record
// Collect file records first to avoid connection deadlock (SetMaxOpenConns=1)
oldFsPath := n.FsPath
oldPhysPath := filepath.Join(a.vault, oldFsPath)
oldTitle := n.Title
parentFsPath := ""
if n.ParentID != nil {
if p, err := a.nodes.GetActive(*n.ParentID); err == nil {
parentFsPath = p.FsPath
}
}
newFsPath := seg
if parentFsPath != "" {
newFsPath = filepath.Join(parentFsPath, seg)
}
newPhysPath := filepath.Join(a.vault, newFsPath)
newPhysPath = templates.UniquePath(newPhysPath)
rel, _ := filepath.Rel(a.vault, newPhysPath)
newFsPath = rel
if _, err := syncsvc.SafeVaultPath(a.vault, newFsPath); err != nil {
return fmt.Errorf("path safety: %w", err)
}
// Pre-collect all descendant fs_path updates (before transaction, to avoid deadlock).
type pathUp struct{ id, path string }
var updates []pathUp
var walk func(string, string)
walk = func(id, p string) {
updates = append(updates, pathUp{id, p})
children, _ := a.nodes.ListChildren(id, false)
for _, c := range children {
cseg := templates.SafeDisplayNameToPathSegment(c.Title)
walk(c.ID, filepath.Join(p, cseg))
}
}
walk(nodeID, newFsPath)
// Check source exists before filesystem rename
if _, err := os.Stat(oldPhysPath); err != nil {
return fmt.Errorf("source folder not found: %w", err)
}
if err := os.Rename(oldPhysPath, newPhysPath); err != nil {
return fmt.Errorf("rename folder: %w", err)
}
// Atomic DB transaction: title + own fs_path + all descendant fs_paths
nowT := time.Now().UTC().Format(time.RFC3339)
slug := nodes.Slugify(newTitle)
tx, err := a.db.Begin()
if err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback()
if _, err := tx.Exec(
`UPDATE nodes SET title=?, slug=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
newTitle, slug, nowT, nodeID); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
for _, u := range updates {
if _, err := tx.Exec(
`UPDATE nodes SET fs_path=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
u.path, nowT, u.id); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
}
if err := tx.Commit(); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return fmt.Errorf("commit tx: %w", err)
}
pid := ""
if n.ParentID != nil {
pid = *n.ParentID
}
_ = a.activity.Record(pid, activity.TargetFolder, nodeID, "", activity.TypeFolderRenamed, newTitle, `{"from":"`+oldTitle+`","to":"`+newTitle+`"}`)
_ = a.sync.RecordOp(syncsvc.EntityFolder, nodeID, syncsvc.OpUpdate, map[string]interface{}{
"title": newTitle,
"fs_path": newFsPath,
"updated_at": time.Now().UTC().Format(time.RFC3339),
})
return nil
}
// renameNoteFileNode renames a note or file node atomically: FS first, then DB transaction.
func (a *App) renameNoteFileNode(nodeID string, n *nodes.Node, newTitle, seg string) error {
// Collect file records before any mutations (avoid deadlock with SetMaxOpenConns=1).
type fileRec struct {
id, path, filename string
}
@ -312,13 +347,13 @@ func (a *App) RenameNode(nodeID, newTitle string) error {
rows.Close()
}
// Collect rename operations without modifying anything yet
// Compute new filenames and paths (no FS modifications yet).
type renameOp struct {
id string
oldFilename string
oldAbs string
newAbs string
newFilename string
newRelPath string
newPath string
}
var renameOps []renameOp
for _, r := range records {
@ -337,10 +372,10 @@ func (a *App) RenameNode(nodeID, newTitle string) error {
} else {
newFilename = newTitle
}
newRelPath := filepath.Join(dir, newFilename)
newAbs := filepath.Join(a.vault, newRelPath)
newPath := filepath.Join(dir, newFilename)
newAbs := filepath.Join(a.vault, newPath)
// Check for collision — generate unique name if needed
// Check for collision
if _, err := os.Stat(newAbs); err == nil {
ext := filepath.Ext(newFilename)
base := strings.TrimSuffix(newFilename, ext)
@ -348,62 +383,79 @@ func (a *App) RenameNode(nodeID, newTitle string) error {
if baseSeg == "" {
baseSeg = "renamed"
}
for n := 2; ; n++ {
candidate := fmt.Sprintf("%s (%d)%s", baseSeg, n, ext)
for i := 2; ; i++ {
candidate := fmt.Sprintf("%s (%d)%s", baseSeg, i, ext)
candidatePath := filepath.Join(dir, candidate)
if _, err := os.Stat(filepath.Join(a.vault, candidatePath)); os.IsNotExist(err) {
newFilename = candidate
newRelPath = candidatePath
newAbs = filepath.Join(a.vault, newRelPath)
newPath = candidatePath
newAbs = filepath.Join(a.vault, newPath)
break
}
}
}
// Check source file exists
if _, err := os.Stat(oldAbs); err != nil {
return fmt.Errorf("source file not found for rename: %w", err)
}
renameOps = append(renameOps, renameOp{
id: r.id,
oldFilename: r.filename,
oldAbs: oldAbs,
newFilename: newFilename,
newRelPath: newRelPath,
id: r.id, oldAbs: oldAbs, newAbs: newAbs,
newFilename: newFilename, newPath: newPath,
})
}
// Perform all physical renames first
for _, rop := range renameOps {
newAbs := filepath.Join(a.vault, rop.newRelPath)
if err := os.Rename(rop.oldAbs, newAbs); err != nil {
// Rollback completed renames
for _, prev := range renameOps {
if prev.id == rop.id {
break
}
_ = os.Rename(filepath.Join(a.vault, prev.newRelPath), prev.oldAbs)
successCount := 0
for i, rop := range renameOps {
if err := os.Rename(rop.oldAbs, rop.newAbs); err != nil {
// Rollback completed FS renames
for j := 0; j < i; j++ {
_ = os.Rename(renameOps[j].newAbs, renameOps[j].oldAbs)
}
return fmt.Errorf("rename file: %w", err)
}
successCount++
}
// All renames succeeded — update DB
if err := a.nodes.UpdateTitle(nodeID, newTitle); err != nil {
// Rollback filesystem
for _, rop := range renameOps {
_ = os.Rename(filepath.Join(a.vault, rop.newRelPath), rop.oldAbs)
// Atomic DB transaction: title + all file record updates
nowT := time.Now().UTC().Format(time.RFC3339)
slug := nodes.Slugify(newTitle)
tx, err := a.db.Begin()
if err != nil {
for _, rop := range renameOps[:successCount] {
_ = os.Rename(rop.newAbs, rop.oldAbs)
}
return fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback()
if _, err := tx.Exec(
`UPDATE nodes SET title=?, slug=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
newTitle, slug, nowT, nodeID); err != nil {
for _, rop := range renameOps[:successCount] {
_ = os.Rename(rop.newAbs, rop.oldAbs)
}
return err
}
for _, rop := range renameOps {
if _, err := a.db.Exec(`UPDATE files SET filename=?, path=? WHERE id=?`,
rop.newFilename, rop.newRelPath, rop.id); err != nil {
if _, err := tx.Exec(
`UPDATE files SET filename=?, path=? WHERE id=?`,
rop.newFilename, rop.newPath, rop.id); err != nil {
for _, rop2 := range renameOps[:successCount] {
_ = os.Rename(rop2.newAbs, rop2.oldAbs)
}
return err
}
}
if err := tx.Commit(); err != nil {
for _, rop := range renameOps[:successCount] {
_ = os.Rename(rop.newAbs, rop.oldAbs)
}
return fmt.Errorf("commit tx: %w", err)
}
pid := ""
if n.ParentID != nil {
pid = *n.ParentID
@ -423,7 +475,7 @@ func (a *App) RenameNode(nodeID, newTitle string) error {
_ = a.activity.Record(pid, targetType, nodeID, "", evType, newTitle, "")
_ = a.sync.RecordOp(syncEntity, nodeID, syncsvc.OpUpdate, map[string]interface{}{
"title": newTitle,
"updated_at": time.Now().UTC().Format(time.RFC3339),
"updated_at": nowT,
})
return nil
}
@ -472,132 +524,253 @@ func (a *App) MoveNode(nodeID, newParentID string) error {
}
}
// Resolve name conflicts first
// Compute new title (name conflict resolution) but don't commit yet.
nodeTitle := node.Title
titleChanged := false
if parent != nil {
destChildren, _ := a.nodes.ListChildren(newParentID, false)
for i := range destChildren {
if destChildren[i].Title == nodeTitle {
if destChildren[i].Title == nodeTitle && destChildren[i].ID != nodeID {
nodeTitle = fmt.Sprintf("%s (%d)", nodeTitle, 2)
titleChanged = true
break
}
}
}
// Update title if changed
if nodeTitle != node.Title {
if err := a.nodes.UpdateTitle(nodeID, nodeTitle); err != nil {
return err
}
node.Title = nodeTitle
if isFolderLike {
return a.moveFolderNode(nodeID, node, parent, newParentID, nodeTitle, titleChanged)
}
return a.moveNoteFileNode(nodeID, node, parent, newParentID, nodeTitle, titleChanged)
}
// moveFolderNode moves a folder-like node atomically: FS first, then DB transaction.
func (a *App) moveFolderNode(nodeID string, node *nodes.Node, parent *nodes.Node, newParentID, nodeTitle string, titleChanged bool) error {
if node.FsPath == "" {
return fmt.Errorf("cannot move node %s (%s): fs_path is empty", node.ID, node.Title)
}
if isFolderLike {
// Folder-like node: move physical directory
if node.FsPath == "" {
return fmt.Errorf("cannot move node %s (%s): fs_path is empty", node.ID, node.Title)
}
oldFsPath := node.FsPath
oldPhysPath := filepath.Join(a.vault, oldFsPath)
seg := templates.SafeDisplayNameToPathSegment(node.Title)
oldPhysPath := filepath.Join(a.vault, node.FsPath)
seg := templates.SafeDisplayNameToPathSegment(nodeTitle)
newFsPath := seg
if parent != nil && parent.FsPath != "" {
newFsPath = filepath.Join(parent.FsPath, seg)
}
newPhysPath := filepath.Join(a.vault, newFsPath)
newPhysPath = templates.UniquePath(newPhysPath)
rel, _ := filepath.Rel(a.vault, newPhysPath)
newFsPath = rel
newFsPath := seg
if parent != nil && parent.FsPath != "" {
newFsPath = filepath.Join(parent.FsPath, seg)
}
newPhysPath := filepath.Join(a.vault, newFsPath)
newPhysPath = templates.UniquePath(newPhysPath)
rel, _ := filepath.Rel(a.vault, newPhysPath)
newFsPath = rel
if _, err := syncsvc.SafeVaultPath(a.vault, newFsPath); err != nil {
return fmt.Errorf("path safety: %w", err)
}
if _, err := syncsvc.SafeVaultPath(a.vault, newFsPath); err != nil {
return fmt.Errorf("path safety: %w", err)
// Pre-collect all descendant fs_path updates (before transaction).
type pathUp struct{ id, path string }
var updates []pathUp
var walk func(string, string)
walk = func(id, p string) {
updates = append(updates, pathUp{id, p})
children, _ := a.nodes.ListChildren(id, false)
for _, c := range children {
cseg := templates.SafeDisplayNameToPathSegment(c.Title)
walk(c.ID, filepath.Join(p, cseg))
}
}
walk(nodeID, newFsPath)
// Check source exists and do filesystem rename first
if _, err := os.Stat(oldPhysPath); err != nil {
return fmt.Errorf("source folder not found: %w", err)
}
if err := os.Rename(oldPhysPath, newPhysPath); err != nil {
return fmt.Errorf("move folder: %w", err)
}
// Check source exists and do filesystem rename first
if _, err := os.Stat(oldPhysPath); err != nil {
return fmt.Errorf("source folder not found: %w", err)
}
if err := os.Rename(oldPhysPath, newPhysPath); err != nil {
return fmt.Errorf("move folder: %w", err)
}
// Update DB only after successful filesystem rename
if newParentID == "" {
if err := a.nodes.Move(nodeID, nil, 0); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
} else {
if err := a.nodes.Move(nodeID, &newParentID, 0); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
}
if err := a.nodes.UpdateFsPath(nodeID, newFsPath); err != nil {
// Atomic DB transaction: title + parent_id + all fs_paths
nowT := time.Now().UTC().Format(time.RFC3339)
tx, err := a.db.Begin()
if err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback()
if titleChanged {
slug := nodes.Slugify(nodeTitle)
if _, err := tx.Exec(
`UPDATE nodes SET title=?, slug=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
nodeTitle, slug, nowT, nodeID); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
if err := a.nodes.UpdateFsPathRecursive(nodeID, newFsPath); err != nil {
}
var parentVal interface{}
if newParentID != "" {
parentVal = newParentID
}
if _, err := tx.Exec(
`UPDATE nodes SET parent_id=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
parentVal, nowT, nodeID); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
// Touch new parent
if newParentID != "" {
_, _ = tx.Exec(`UPDATE nodes SET updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`, nowT, newParentID)
}
// Touch old parent if different
if node.ParentID != nil && *node.ParentID != newParentID {
_, _ = tx.Exec(`UPDATE nodes SET updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`, nowT, *node.ParentID)
}
for _, u := range updates {
if _, err := tx.Exec(
`UPDATE nodes SET fs_path=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
u.path, nowT, u.id); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return err
}
}
node.FsPath = newFsPath
if err := tx.Commit(); err != nil {
_ = os.Rename(newPhysPath, oldPhysPath)
return fmt.Errorf("commit tx: %w", err)
}
// Update node.ParentID for activity/sync below
if newParentID == "" {
node.ParentID = nil
} else {
// Note/file node: move physical file first, then update DB
var fileMoves []fileMoveInfo
frows, ferr := a.db.Query(`SELECT id, path FROM files WHERE node_id=?`, nodeID)
if ferr == nil {
for frows.Next() {
var fm fileMoveInfo
if err := frows.Scan(&fm.id, &fm.oldPath); err != nil {
continue
}
if fm.oldPath == "" {
continue
}
filename := filepath.Base(fm.oldPath)
fm.newRelPath = filename
if parent != nil && parent.FsPath != "" {
fm.newRelPath = filepath.Join(parent.FsPath, filename)
}
fileMoves = append(fileMoves, fm)
}
frows.Close()
}
node.ParentID = &newParentID
}
node.FsPath = newFsPath
// Perform filesystem moves first
for _, fm := range fileMoves {
oldAbs := filepath.Join(a.vault, fm.oldPath)
newAbs := filepath.Join(a.vault, fm.newRelPath)
if _, err := os.Stat(oldAbs); err != nil {
return fmt.Errorf("source file not found for move: %w", err)
}
_ = os.MkdirAll(filepath.Dir(newAbs), 0o750)
if err := os.Rename(oldAbs, newAbs); err != nil {
return fmt.Errorf("move file: %w", err)
}
}
pid := ""
if node.ParentID != nil {
pid = *node.ParentID
}
_ = a.activity.Record(pid, activity.TargetFolder, nodeID, "", activity.TypeFolderMoved, nodeTitle, `{"to":"`+newParentID+`"}`)
_ = a.sync.RecordOp(syncsvc.EntityFolder, nodeID, syncsvc.OpMove, map[string]interface{}{
"parent_id": newParentID,
"fs_path": newFsPath,
"updated_at": nowT,
})
return nil
}
// Update DB only after successful filesystem renames
if newParentID == "" {
if err := a.nodes.Move(nodeID, nil, 0); err != nil {
_ = a.rollbackFileMoves(fileMoves)
return err
// moveNoteFileNode moves a note/file atomically: FS first, then DB transaction.
func (a *App) moveNoteFileNode(nodeID string, node *nodes.Node, parent *nodes.Node, newParentID, nodeTitle string, titleChanged bool) error {
// Collect file records before any mutations.
type fileMove struct {
id string
oldPath string
oldAbs string
newRelPath string
newAbs string
}
var fileMoves []fileMove
frows, ferr := a.db.Query(`SELECT id, path FROM files WHERE node_id=?`, nodeID)
if ferr == nil {
for frows.Next() {
var fm fileMove
if err := frows.Scan(&fm.id, &fm.oldPath); err != nil {
continue
}
} else {
if err := a.nodes.Move(nodeID, &newParentID, 0); err != nil {
_ = a.rollbackFileMoves(fileMoves)
return err
if fm.oldPath == "" {
continue
}
fm.oldAbs = filepath.Join(a.vault, fm.oldPath)
filename := filepath.Base(fm.oldPath)
fm.newRelPath = filename
if parent != nil && parent.FsPath != "" {
fm.newRelPath = filepath.Join(parent.FsPath, filename)
}
fm.newAbs = filepath.Join(a.vault, fm.newRelPath)
fileMoves = append(fileMoves, fm)
}
frows.Close()
}
// Perform filesystem moves first (with rollback on partial failure).
for i, fm := range fileMoves {
if _, err := os.Stat(fm.oldAbs); err != nil {
for j := 0; j < i; j++ {
_ = os.Rename(fileMoves[j].newAbs, fileMoves[j].oldAbs)
}
return fmt.Errorf("source file not found for move: %w", err)
}
_ = os.MkdirAll(filepath.Dir(fm.newAbs), 0o750)
if err := os.Rename(fm.oldAbs, fm.newAbs); err != nil {
for j := 0; j < i; j++ {
_ = os.Rename(fileMoves[j].newAbs, fileMoves[j].oldAbs)
}
return fmt.Errorf("move file: %w", err)
}
}
// Atomic DB transaction: title + parent_id + file paths
nowT := time.Now().UTC().Format(time.RFC3339)
tx, err := a.db.Begin()
if err != nil {
for _, fm := range fileMoves {
if _, err := a.db.Exec(`UPDATE files SET path=? WHERE id=?`,
fm.newRelPath, fm.id); err != nil {
return err
}
_ = os.Rename(fm.newAbs, fm.oldAbs)
}
return fmt.Errorf("begin tx: %w", err)
}
defer tx.Rollback()
if titleChanged {
slug := nodes.Slugify(nodeTitle)
if _, err := tx.Exec(
`UPDATE nodes SET title=?, slug=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
nodeTitle, slug, nowT, nodeID); err != nil {
for _, fm := range fileMoves {
_ = os.Rename(fm.newAbs, fm.oldAbs)
}
return err
}
}
var parentVal interface{}
if newParentID != "" {
parentVal = newParentID
}
if _, err := tx.Exec(
`UPDATE nodes SET parent_id=?, updated_at=?, revision=revision+1 WHERE id=? AND deleted_at IS NULL`,
parentVal, nowT, nodeID); err != nil {
for _, fm := range fileMoves {
_ = os.Rename(fm.newAbs, fm.oldAbs)
}
return err
}
for _, fm := range fileMoves {
if _, err := tx.Exec(`UPDATE files SET path=? WHERE id=?`,
fm.newRelPath, fm.id); err != nil {
for _, fm2 := range fileMoves {
_ = os.Rename(fm2.newAbs, fm2.oldAbs)
}
return err
}
}
if err := tx.Commit(); err != nil {
for _, fm := range fileMoves {
_ = os.Rename(fm.newAbs, fm.oldAbs)
}
return fmt.Errorf("commit tx: %w", err)
}
if newParentID == "" {
node.ParentID = nil
} else {
node.ParentID = &newParentID
}
pid := ""
@ -607,11 +780,7 @@ func (a *App) MoveNode(nodeID, newParentID string) error {
var targetType string
var evType string
var syncEntity string
if isFolderLike {
targetType = activity.TargetFolder
evType = activity.TypeFolderMoved
syncEntity = syncsvc.EntityFolder
} else if node.Type == nodes.TypeNote {
if node.Type == nodes.TypeNote {
targetType = activity.TargetNote
evType = activity.TypeNoteUpdated
syncEntity = syncsvc.EntityNote
@ -620,15 +789,11 @@ func (a *App) MoveNode(nodeID, newParentID string) error {
evType = activity.TypeFileMoved
syncEntity = syncsvc.EntityFile
}
_ = a.activity.Record(pid, targetType, nodeID, "", evType, node.Title, `{"to":"`+newParentID+`"}`)
opPayload := map[string]interface{}{
_ = a.activity.Record(pid, targetType, nodeID, "", evType, nodeTitle, `{"to":"`+newParentID+`"}`)
_ = a.sync.RecordOp(syncEntity, nodeID, syncsvc.OpMove, map[string]interface{}{
"parent_id": newParentID,
"updated_at": time.Now().UTC().Format(time.RFC3339),
}
if isFolderLike && node.FsPath != "" {
opPayload["fs_path"] = node.FsPath
}
_ = a.sync.RecordOp(syncEntity, nodeID, syncsvc.OpMove, opPayload)
"updated_at": nowT,
})
return nil
}