This commit is contained in:
Daniel 2025-03-28 21:32:09 +08:00
parent f43699b2c4
commit 1cb8520700
No known key found for this signature in database
GPG key ID: 86211BA83DF03017
4 changed files with 151 additions and 87 deletions

View file

@ -26,7 +26,6 @@ import {isTouchDevice} from "../../util/functions";
import {App} from "../../index"; import {App} from "../../index";
import {refreshFileTree} from "../../dialog/processSystem"; import {refreshFileTree} from "../../dialog/processSystem";
import {hideTooltip, showTooltip} from "../../dialog/tooltip"; import {hideTooltip, showTooltip} from "../../dialog/tooltip";
import * as dayjs from "dayjs";
export class Files extends Model { export class Files extends Model {
public element: HTMLElement; public element: HTMLElement;
@ -325,8 +324,7 @@ export class Files extends Model {
}); });
} else if (type === "addLocal") { } else if (type === "addLocal") {
fetchPost("/api/filetree/moveLocalShorthands", { fetchPost("/api/filetree/moveLocalShorthands", {
"notebook": notebookId, "notebook": notebookId
"path": dayjs().format("YYYY-MM-DD HH:mm:ss")
}); });
this.element.querySelectorAll('[data-type="addLocal"]').forEach(item => { this.element.querySelectorAll('[data-type="addLocal"]').forEach(item => {
item.remove(); item.remove();

View file

@ -1,8 +1,4 @@
import { import {hasClosestByClassName, hasClosestByTag, hasTopClosestByTag} from "../../protyle/util/hasClosest";
hasClosestByClassName,
hasClosestByTag,
hasTopClosestByTag
} from "../../protyle/util/hasClosest";
import {escapeHtml} from "../../util/escape"; import {escapeHtml} from "../../util/escape";
import {Model} from "../../layout/Model"; import {Model} from "../../layout/Model";
import {Constants} from "../../constants"; import {Constants} from "../../constants";
@ -20,7 +16,6 @@ import {MenuItem} from "../../menus/Menu";
import {App} from "../../index"; import {App} from "../../index";
import {refreshFileTree} from "../../dialog/processSystem"; import {refreshFileTree} from "../../dialog/processSystem";
import {setStorageVal} from "../../protyle/util/compatibility"; import {setStorageVal} from "../../protyle/util/compatibility";
import * as dayjs from "dayjs";
export class MobileFiles extends Model { export class MobileFiles extends Model {
public element: HTMLElement; public element: HTMLElement;
@ -220,8 +215,7 @@ export class MobileFiles extends Model {
window.siyuan.menus.menu.fullscreen("bottom"); window.siyuan.menus.menu.fullscreen("bottom");
} else if (type === "addLocal") { } else if (type === "addLocal") {
fetchPost("/api/filetree/moveLocalShorthands", { fetchPost("/api/filetree/moveLocalShorthands", {
"notebook": notebookId, "notebook": notebookId
"path": dayjs().format("YYYY-MM-DD HH:mm:ss")
}); });
this.element.querySelectorAll('[data-type="addLocal"]').forEach(item => { this.element.querySelectorAll('[data-type="addLocal"]').forEach(item => {
item.remove(); item.remove();

View file

@ -55,13 +55,10 @@ func moveLocalShorthands(c *gin.Context) {
parentID = parentIDArg.(string) parentID = parentIDArg.(string)
} }
id := ast.NewNodeID() var hPath string
idArg := arg["id"] hPathArg := arg["path"]
if nil != idArg { if nil != hPathArg {
id = idArg.(string) hPath = arg["path"].(string)
}
hPath := arg["path"].(string)
baseName := path.Base(hPath) baseName := path.Base(hPath)
dir := path.Dir(hPath) dir := path.Dir(hPath)
r, _ := regexp.Compile("\r\n|\r|\n|\u2028|\u2029|\t|/") r, _ := regexp.Compile("\r\n|\r|\n|\u2028|\u2029|\t|/")
@ -70,29 +67,22 @@ func moveLocalShorthands(c *gin.Context) {
baseName = gulu.Str.SubStr(baseName, 512) baseName = gulu.Str.SubStr(baseName, 512)
} }
hPath = path.Join(dir, baseName) hPath = path.Join(dir, baseName)
if !strings.HasPrefix(hPath, "/") {
hPath = "/" + hPath
} }
id, err := model.MoveLocalShorthands(notebook, hPath, parentID, id) ids, err := model.MoveLocalShorthands(notebook, hPath, parentID)
if err != nil { if err != nil {
ret.Code = -1 ret.Code = -1
ret.Msg = err.Error() ret.Msg = err.Error()
return return
} }
if "" == id {
ret.Code = 1
ret.Msg = "No local shorthand need to move"
return
}
ret.Data = id
model.FlushTxQueue() model.FlushTxQueue()
box := model.Conf.Box(notebook) box := model.Conf.Box(notebook)
for _, id := range ids {
b, _ := model.GetBlock(id, nil) b, _ := model.GetBlock(id, nil)
pushCreate(box, b.Path, arg) pushCreate(box, b.Path, arg)
} }
}
func listDocTree(c *gin.Context) { func listDocTree(c *gin.Context) {
// Add kernel API `/api/filetree/listDocTree` https://github.com/siyuan-note/siyuan/issues/10482 // Add kernel API `/api/filetree/listDocTree` https://github.com/siyuan-note/siyuan/issues/10482

View file

@ -20,14 +20,20 @@ import (
"bytes" "bytes"
"os" "os"
"path/filepath" "path/filepath"
"slices"
"strconv"
"strings" "strings"
"time"
"github.com/88250/gulu" "github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/88250/lute/parse"
"github.com/siyuan-note/logging" "github.com/siyuan-note/logging"
"github.com/siyuan-note/siyuan/kernel/treenode"
"github.com/siyuan-note/siyuan/kernel/util" "github.com/siyuan-note/siyuan/kernel/util"
) )
func MoveLocalShorthands(boxID, hPath, parentID, id string) (retID string, err error) { func MoveLocalShorthands(boxID, hPath, parentID string) (retIDs []string, err error) {
shorthandsDir := filepath.Join(util.ShortcutsPath, "shorthands") shorthandsDir := filepath.Join(util.ShortcutsPath, "shorthands")
if !gulu.File.IsDir(shorthandsDir) { if !gulu.File.IsDir(shorthandsDir) {
return return
@ -39,12 +45,9 @@ func MoveLocalShorthands(boxID, hPath, parentID, id string) (retID string, err e
return return
} }
buff := bytes.Buffer{}
var toRemoves []string
assetsDir := filepath.Join(util.DataDir, "assets") assetsDir := filepath.Join(util.DataDir, "assets")
for _, entry := range entries { for _, entry := range entries {
if entry.IsDir() { if entry.IsDir() && "assets" == entry.Name() {
if "assets" == entry.Name() {
assetsEntries, readErr := os.ReadDir(filepath.Join(shorthandsDir, entry.Name())) assetsEntries, readErr := os.ReadDir(filepath.Join(shorthandsDir, entry.Name()))
if nil != readErr { if nil != readErr {
logging.LogErrorf("read dir [%s] failed: %s", shorthandsDir, readErr) logging.LogErrorf("read dir [%s] failed: %s", shorthandsDir, readErr)
@ -65,6 +68,11 @@ func MoveLocalShorthands(boxID, hPath, parentID, id string) (retID string, err e
} }
} }
var toRemoves []string
box := Conf.Box(boxID)
if "" == hPath { // hPath 为空的话每一个速记对应创建一个文档记录
for _, entry := range entries {
if filepath.Ext(entry.Name()) != ".md" { if filepath.Ext(entry.Name()) != ".md" {
continue continue
} }
@ -76,32 +84,106 @@ func MoveLocalShorthands(boxID, hPath, parentID, id string) (retID string, err e
continue continue
} }
buff.Write(bytes.TrimSpace(data)) content := string(bytes.TrimSpace(data))
buff.WriteString("\n\n") if "" == content {
toRemoves = append(toRemoves, p) toRemoves = append(toRemoves, p)
continue
} }
clearShorthand := func(toRemoves []string) { t := strings.TrimSuffix(entry.Name(), ".md")
for _, p := range toRemoves { i, parseErr := strconv.ParseInt(t, 10, 64)
if removeErr := os.Remove(p); nil != removeErr { if nil != parseErr {
logging.LogErrorf("remove file [%s] failed: %s", p, removeErr) logging.LogErrorf("parse [%s] to int failed: %s", t, parseErr)
continue
} }
} hPath = "/" + time.UnixMilli(i).Format("2006-01-02 15:04:05")
} var retID string
retID, err = CreateWithMarkdown("", boxID, hPath, content, parentID, "", false, "")
content := strings.TrimSpace(buff.String())
if 1 > len(content) {
clearShorthand(toRemoves)
return
}
retID, err = CreateWithMarkdown("", boxID, hPath, content, parentID, id, false, "")
if nil != err { if nil != err {
logging.LogErrorf("create doc failed: %s", err) logging.LogErrorf("create doc failed: %s", err)
return return
} }
clearShorthand(toRemoves) retIDs = append(retIDs, retID)
toRemoves = append(toRemoves, p)
box.addMinSort("/", retID)
}
} else { // 不为空的话将所有速记合并到指定路径的文档中
if !strings.HasPrefix(hPath, "/") {
hPath = "/" + hPath
}
buff := bytes.Buffer{}
for _, entry := range entries {
if filepath.Ext(entry.Name()) != ".md" {
continue
}
p := filepath.Join(shorthandsDir, entry.Name())
data, readErr := os.ReadFile(p)
if nil != readErr {
logging.LogErrorf("read file [%s] failed: %s", p, readErr)
continue
}
content := string(bytes.TrimSpace(data))
if "" == content {
toRemoves = append(toRemoves, p)
continue
}
buff.WriteString(content)
buff.WriteString("\n\n")
toRemoves = append(toRemoves, p)
}
if 0 < buff.Len() {
bt := treenode.GetBlockTreeRootByHPath(boxID, hPath)
if nil == bt {
var retID string
retID, err = CreateWithMarkdown("", boxID, hPath, buff.String(), parentID, "", false, "")
if nil != err {
logging.LogErrorf("create doc failed: %s", err)
return
}
retIDs = append(retIDs, retID)
} else {
var tree *parse.Tree
tree, err = loadTreeByBlockTree(bt)
if nil != err {
logging.LogErrorf("load tree by block tree failed: %s", err)
return
}
var last *ast.Node
for c := tree.Root.FirstChild; nil != c; c = c.Next {
last = c
}
luteEngine := util.NewStdLute()
inputTree := parse.Parse("", buff.Bytes(), luteEngine.ParseOptions)
if nil != inputTree {
var nodes []*ast.Node
for c := inputTree.Root.FirstChild; nil != c; c = c.Next {
nodes = append(nodes, c)
}
slices.Reverse(nodes)
for _, node := range nodes {
last.InsertAfter(node)
}
}
indexWriteTreeIndexQueue(tree)
}
}
}
for _, p := range toRemoves {
if removeErr := os.Remove(p); nil != removeErr {
logging.LogErrorf("remove file [%s] failed: %s", p, removeErr)
}
}
return return
} }