diff --git a/app/appearance/langs/en_US.json b/app/appearance/langs/en_US.json index e9e761a11..8b853e145 100644 --- a/app/appearance/langs/en_US.json +++ b/app/appearance/langs/en_US.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "Visit community share", "clearContextSucc": "The context has been cleared", "emptyMobilePlaceholder": "Record something", "emptyPlaceholder": "Write something, ' / ' for commands", @@ -466,6 +467,7 @@ "floatWindowMode1": "Press and hold ${hotkey}+Hover", "floatWindowMode2": "Do not trigger", "codeSnippet": "Code Snippet", + "codeSnippetTip": "Fine-tune the interface or functionality through code snippets", "expandDown": "Expand Down", "expandUp": "Expand Up", "goForward": "Go forward", diff --git a/app/appearance/langs/es_ES.json b/app/appearance/langs/es_ES.json index 1a7f1cbed..f9c8dcaef 100644 --- a/app/appearance/langs/es_ES.json +++ b/app/appearance/langs/es_ES.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "Visitar la comunidad compartida", "clearContextSucc": "Se ha borrado el contexto", "emptyMobilePlaceholder": "Grabar algo", "emptyPlaceholder": "Escribe algo, ' / ' para los comandos", @@ -466,6 +467,7 @@ "floatWindowMode1": "Presione y mantenga presionado ${hotkey}+Flotar", "floatWindowMode2": "No activar", "codeSnippet": "Fragmento de código", + "codeSnippetTip": "Ajusta la interfaz o la funcionalidad mediante fragmentos de código", "expandDown": "Expandir hacia abajo", "expandUp": "Expandir hacia arriba", "goForward": "Ir hacia adelante", diff --git a/app/appearance/langs/fr_FR.json b/app/appearance/langs/fr_FR.json index 1319a0112..4a9cfabb9 100644 --- a/app/appearance/langs/fr_FR.json +++ b/app/appearance/langs/fr_FR.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "Visiter le partage communautaire", "clearContextSucc": "Le contexte a été effacé", "emptyMobilePlaceholder": "Enregistrer quelque chose", "emptyPlaceholder": "Écrivez quelque chose, ' / ' pour les commandes", @@ -466,6 +467,7 @@ "floatWindowMode1": "Appuyez et maintenez ${hotkey}+Flotter", "floatWindowMode2": "Ne pas déclencher", "codeSnippet": "Extrait de code", + "codeSnippetTip": "Affiner l'interface ou les fonctionnalités grâce à des extraits de code", "expandDown": "Développer vers le bas", "expandUp": "Développer vers le haut", "goForward": "Suivant", diff --git a/app/appearance/langs/ja_JP.json b/app/appearance/langs/ja_JP.json index c45735c4b..ca0fa4aba 100644 --- a/app/appearance/langs/ja_JP.json +++ b/app/appearance/langs/ja_JP.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "コミュニティシェアを訪問", "clearContextSucc": "コンテキストがクリアされました", "emptyMobilePlaceholder": "何かを記録する", "emptyPlaceholder": "何か書いてください。コマンドの場合は「/」", @@ -466,6 +467,7 @@ "floatWindowMode1": "${hotkey} を押しながらホバー", "floatWindowMode2": "表示しない", "codeSnippet": "コードスニペット", + "codeSnippetTip": "コード スニペットを通じてインターフェイスまたは機能を微調整します", "expandDown": "選択範囲を下に拡張", "expandUp": "選択範囲を上に拡張", "goForward": "進む", diff --git a/app/appearance/langs/zh_CHT.json b/app/appearance/langs/zh_CHT.json index fb5127291..c87e52021 100644 --- a/app/appearance/langs/zh_CHT.json +++ b/app/appearance/langs/zh_CHT.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "訪問社區分享", "clearContextSucc": "上下文已清空", "emptyMobilePlaceholder": "記錄點什麼", "emptyPlaceholder": "寫點什麼,或按下 ' / ' 查看指令", @@ -466,6 +467,7 @@ "floatWindowMode1": "按住 ${hotkey}+懸停", "floatWindowMode2": "不觸發浮窗", "codeSnippet": "代碼片段", + "codeSnippetTip": "透過程式碼片段對介面或功能進行微調", "expandDown": "向下擴選", "expandUp": "向上擴選", "goForward": "前進", diff --git a/app/appearance/langs/zh_CN.json b/app/appearance/langs/zh_CN.json index 1d72dda1a..8444223d1 100644 --- a/app/appearance/langs/zh_CN.json +++ b/app/appearance/langs/zh_CN.json @@ -1,4 +1,5 @@ { + "visitCommunityShare": "访问社区分享", "clearContextSucc": "上下文已清空", "emptyMobilePlaceholder": "记录点什么", "emptyPlaceholder": "写点什么,或按下 ' / ' 查看命令", @@ -466,6 +467,7 @@ "floatWindowMode1": "按住 ${hotkey}+悬停", "floatWindowMode2": "不触发浮窗", "codeSnippet": "代码片段", + "codeSnippetTip": "通过代码片段对界面或功能进行微调", "expandDown": "向下扩选", "expandUp": "向上扩选", "goForward": "前进", diff --git a/app/src/config/appearance.ts b/app/src/config/appearance.ts index 0ece8950f..30246620a 100644 --- a/app/src/config/appearance.ts +++ b/app/src/config/appearance.ts @@ -121,8 +121,13 @@ export const appearance = {
${window.siyuan.languages.codeSnippet} +
${window.siyuan.languages.codeSnippetTip}
+ + ${window.siyuan.languages.visitCommunityShare} + + diff --git a/kernel/api/workspace.go b/kernel/api/workspace.go index be1d90eb3..1cec139eb 100644 --- a/kernel/api/workspace.go +++ b/kernel/api/workspace.go @@ -27,7 +27,6 @@ import ( "unicode/utf8" "github.com/88250/gulu" - "github.com/facette/natsort" "github.com/gin-gonic/gin" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/model" @@ -252,10 +251,10 @@ func getWorkspaces(c *gin.Context) { } } sort.Slice(openedWorkspaces, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(filepath.Base(openedWorkspaces[i].Path)), util.RemoveEmojiInvisible(filepath.Base(openedWorkspaces[j].Path))) + return util.NaturalCompare(filepath.Base(openedWorkspaces[i].Path), filepath.Base(openedWorkspaces[j].Path)) }) sort.Slice(closedWorkspaces, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(filepath.Base(closedWorkspaces[i].Path)), util.RemoveEmojiInvisible(filepath.Base(closedWorkspaces[j].Path))) + return util.NaturalCompare(filepath.Base(closedWorkspaces[i].Path), filepath.Base(closedWorkspaces[j].Path)) }) workspaces = append(workspaces, openedWorkspaces...) workspaces = append(workspaces, closedWorkspaces...) diff --git a/kernel/av/sort.go b/kernel/av/sort.go index 5b18b372c..a2505cd59 100644 --- a/kernel/av/sort.go +++ b/kernel/av/sort.go @@ -44,7 +44,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { switch value.Type { case KeyTypeBlock: if nil != value.Block && nil != other.Block { - return strings.Compare(value.Block.Content, other.Block.Content) + if util.PinYinCompare(value.Block.Content, other.Block.Content) { + return -1 + } + return 1 } case KeyTypeText: if nil != value.Text && nil != other.Text { @@ -56,7 +59,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { } else if "" == other.Text.Content { return -1 } - return strings.Compare(value.Text.Content, other.Text.Content) + if util.PinYinCompare(value.Text.Content, other.Text.Content) { + return -1 + } + return 1 } case KeyTypeNumber: if nil != value.Number && nil != other.Number { @@ -223,7 +229,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { for _, v := range other.MAsset { v2 += v.Content } - return strings.Compare(v1, v2) + if util.PinYinCompare(v1, v2) { + return -1 + } + return 1 } case KeyTypeTemplate: if nil != value.Template && nil != other.Template { @@ -238,7 +247,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { } return 0 } - return strings.Compare(value.Template.Content, other.Template.Content) + if util.PinYinCompare(value.Template.Content, other.Template.Content) { + return -1 + } + return 1 } case KeyTypeCheckbox: if nil != value.Checkbox && nil != other.Checkbox { @@ -278,7 +290,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { oContentBuf.WriteByte(' ') } oContent := strings.TrimSpace(oContentBuf.String()) - return strings.Compare(vContent, oContent) + if util.PinYinCompare(vContent, oContent) { + return -1 + } + return 1 } case KeyTypeRollup: if nil != value.Rollup && nil != other.Rollup { @@ -308,7 +323,10 @@ func (value *Value) Compare(other *Value, attrView *AttributeView) int { oContentBuf.WriteByte(' ') } oContent := strings.TrimSpace(oContentBuf.String()) - return strings.Compare(vContent, oContent) + if util.PinYinCompare(vContent, oContent) { + return -1 + } + return 1 } } return 0 diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 524ddc6c6..36ce476ce 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -75,6 +75,23 @@ func AppendAttributeViewDetachedBlocksWithValues(avID string, blocksValues [][]* v.UpdatedAt = now keyValues.Values = append(keyValues.Values, v) + + if av.KeyTypeSelect == v.Type || av.KeyTypeMSelect == v.Type { + // 保存选项 https://github.com/siyuan-note/siyuan/issues/12475 + key, _ := attrView.GetKey(v.KeyID) + if nil != key && 0 < len(v.MSelect) { + for _, valOpt := range v.MSelect { + if opt := key.GetOption(valOpt.Content); nil == opt { + // 不存在的选项新建保存 + opt = &av.SelectOption{Name: valOpt.Content, Color: valOpt.Color} + key.Options = append(key.Options, opt) + } else { + // 已经存在的选项颜色需要保持不变 + valOpt.Color = opt.Color + } + } + } + } } } diff --git a/kernel/model/backlink.go b/kernel/model/backlink.go index 8950ed4ca..f8a35a659 100644 --- a/kernel/model/backlink.go +++ b/kernel/model/backlink.go @@ -29,7 +29,6 @@ import ( "github.com/88250/lute/ast" "github.com/88250/lute/parse" "github.com/emirpasic/gods/sets/hashset" - "github.com/facette/natsort" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/search" "github.com/siyuan-note/siyuan/kernel/sql" @@ -275,13 +274,13 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode case util.SortModeCreatedASC: return backlinks[i].Created < backlinks[j].Created case util.SortModeNameDESC: - return util.PinYinCompare(util.RemoveEmojiInvisible(backlinks[j].Name), util.RemoveEmojiInvisible(backlinks[i].Name)) + return util.PinYinCompare(backlinks[j].Name, backlinks[i].Name) case util.SortModeNameASC: - return util.PinYinCompare(util.RemoveEmojiInvisible(backlinks[i].Name), util.RemoveEmojiInvisible(backlinks[j].Name)) + return util.PinYinCompare(backlinks[i].Name, backlinks[j].Name) case util.SortModeAlphanumDESC: - return natsort.Compare(util.RemoveEmojiInvisible(backlinks[j].Name), util.RemoveEmojiInvisible(backlinks[i].Name)) + return util.NaturalCompare(backlinks[j].Name, backlinks[i].Name) case util.SortModeAlphanumASC: - return natsort.Compare(util.RemoveEmojiInvisible(backlinks[i].Name), util.RemoveEmojiInvisible(backlinks[j].Name)) + return util.NaturalCompare(backlinks[i].Name, backlinks[j].Name) } return backlinks[i].ID > backlinks[j].ID }) @@ -304,13 +303,13 @@ func GetBacklink2(id, keyword, mentionKeyword string, sortMode, mentionSortMode case util.SortModeCreatedASC: return backmentions[i].Created < backmentions[j].Created case util.SortModeNameDESC: - return util.PinYinCompare(util.RemoveEmojiInvisible(backmentions[j].Name), util.RemoveEmojiInvisible(backmentions[i].Name)) + return util.PinYinCompare(backmentions[j].Name, backmentions[i].Name) case util.SortModeNameASC: - return util.PinYinCompare(util.RemoveEmojiInvisible(backmentions[i].Name), util.RemoveEmojiInvisible(backmentions[j].Name)) + return util.PinYinCompare(backmentions[i].Name, backmentions[j].Name) case util.SortModeAlphanumDESC: - return natsort.Compare(util.RemoveEmojiInvisible(backmentions[j].Name), util.RemoveEmojiInvisible(backmentions[i].Name)) + return util.NaturalCompare(backmentions[j].Name, backmentions[i].Name) case util.SortModeAlphanumASC: - return natsort.Compare(util.RemoveEmojiInvisible(backmentions[i].Name), util.RemoveEmojiInvisible(backmentions[j].Name)) + return util.NaturalCompare(backmentions[i].Name, backmentions[j].Name) } return backmentions[i].ID > backmentions[j].ID }) @@ -520,7 +519,7 @@ func buildLinkRefs(defRootID string, refs []*sql.Ref, keyword string) (ret []*Bl } var paragraphParentIDs []string - for parentID, _ := range parentRefParagraphs { + for parentID := range parentRefParagraphs { paragraphParentIDs = append(paragraphParentIDs, parentID) } sqlParagraphParents := sql.GetBlocks(paragraphParentIDs) diff --git a/kernel/model/box.go b/kernel/model/box.go index 20f1304bb..3135e5d72 100644 --- a/kernel/model/box.go +++ b/kernel/model/box.go @@ -34,7 +34,6 @@ import ( "github.com/88250/lute/html" "github.com/88250/lute/lex" "github.com/88250/lute/parse" - "github.com/facette/natsort" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/cache" @@ -150,30 +149,30 @@ func ListNotebooks() (ret []*Box, err error) { switch Conf.FileTree.Sort { case util.SortModeNameASC: sort.Slice(ret, func(i, j int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(ret[i].Name), util.RemoveEmojiInvisible(ret[j].Name)) + return util.PinYinCompare(ret[i].Name, ret[j].Name) }) case util.SortModeNameDESC: sort.Slice(ret, func(i, j int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(ret[j].Name), util.RemoveEmojiInvisible(ret[i].Name)) + return util.PinYinCompare(ret[j].Name, ret[i].Name) }) case util.SortModeUpdatedASC: case util.SortModeUpdatedDESC: case util.SortModeAlphanumASC: sort.Slice(ret, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(ret[i].Name), util.RemoveEmojiInvisible(ret[j].Name)) + return util.NaturalCompare(ret[i].Name, ret[j].Name) }) case util.SortModeAlphanumDESC: sort.Slice(ret, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(ret[j].Name), util.RemoveEmojiInvisible(ret[i].Name)) + return util.NaturalCompare(ret[j].Name, ret[i].Name) }) case util.SortModeCustom: sort.Slice(ret, func(i, j int) bool { return ret[i].Sort < ret[j].Sort }) case util.SortModeRefCountASC: case util.SortModeRefCountDESC: case util.SortModeCreatedASC: - sort.Slice(ret, func(i, j int) bool { return natsort.Compare(ret[j].ID, ret[i].ID) }) + sort.Slice(ret, func(i, j int) bool { return util.NaturalCompare(ret[j].ID, ret[i].ID) }) case util.SortModeCreatedDESC: - sort.Slice(ret, func(i, j int) bool { return natsort.Compare(ret[j].ID, ret[i].ID) }) + sort.Slice(ret, func(i, j int) bool { return util.NaturalCompare(ret[j].ID, ret[i].ID) }) } return } diff --git a/kernel/model/export.go b/kernel/model/export.go index 02c379b25..5a1b8138e 100644 --- a/kernel/model/export.go +++ b/kernel/model/export.go @@ -454,6 +454,8 @@ func ExportData() (zipPath string, err error) { func exportData(exportFolder string) (zipPath string, err error) { WaitForWritingFiles() + logging.LogInfof("exporting data...") + baseFolderName := "data-" + util.CurrentTimeSecondsStr() if err = os.MkdirAll(exportFolder, 0755); err != nil { logging.LogErrorf("create export temp folder failed: %s", err) @@ -489,6 +491,7 @@ func exportData(exportFolder string) (zipPath string, err error) { } os.RemoveAll(exportFolder) + logging.LogInfof("export data done [%s]", zipPath) return } diff --git a/kernel/model/file.go b/kernel/model/file.go index 3f67730aa..5765b5d93 100644 --- a/kernel/model/file.go +++ b/kernel/model/file.go @@ -37,7 +37,6 @@ import ( "github.com/88250/lute/html" "github.com/88250/lute/parse" util2 "github.com/88250/lute/util" - "github.com/facette/natsort" jsoniter "github.com/json-iterator/go" "github.com/siyuan-note/filelock" "github.com/siyuan-note/logging" @@ -388,11 +387,11 @@ func ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden boo switch sortMode { case util.SortModeNameASC: sort.Slice(docs, func(i, j int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(docs[i].Name), util.RemoveEmojiInvisible(docs[j].Name)) + return util.PinYinCompare(docs[i].Name, docs[j].Name) }) case util.SortModeNameDESC: sort.Slice(docs, func(i, j int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(docs[j].Name), util.RemoveEmojiInvisible(docs[i].Name)) + return util.PinYinCompare(docs[j].Name, docs[i].Name) }) case util.SortModeUpdatedASC: sort.Slice(docs, func(i, j int) bool { return docs[i].Mtime < docs[j].Mtime }) @@ -400,11 +399,11 @@ func ListDocTree(boxID, listPath string, sortMode int, flashcard, showHidden boo sort.Slice(docs, func(i, j int) bool { return docs[i].Mtime > docs[j].Mtime }) case util.SortModeAlphanumASC: sort.Slice(docs, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(docs[i].Name), util.RemoveEmojiInvisible(docs[j].Name)) + return util.NaturalCompare(docs[i].Name, docs[j].Name) }) case util.SortModeAlphanumDESC: sort.Slice(docs, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible(docs[j].Name), util.RemoveEmojiInvisible(docs[i].Name)) + return util.NaturalCompare(docs[j].Name, docs[i].Name) }) case util.SortModeCustom: fileTreeFiles := docs diff --git a/kernel/model/tag.go b/kernel/model/tag.go index 1f598fdb7..8a84cdd48 100644 --- a/kernel/model/tag.go +++ b/kernel/model/tag.go @@ -24,7 +24,6 @@ import ( "github.com/88250/lute/ast" "github.com/emirpasic/gods/sets/hashset" - "github.com/facette/natsort" "github.com/siyuan-note/logging" "github.com/siyuan-note/siyuan/kernel/search" "github.com/siyuan-note/siyuan/kernel/sql" @@ -216,7 +215,7 @@ func BuildTags() (ret *Tags) { ret = &Tags{} labels := labelTags() tags := Tags{} - for label, _ := range labels { + for label := range labels { tags = buildTags(tags, strings.Split(label, "/"), 0) } appendTagChildren(&tags, labels) @@ -248,19 +247,19 @@ func sortTags(tags Tags) { switch Conf.Tag.Sort { case util.SortModeNameASC: sort.Slice(tags, func(i, j int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(tags[i].Name), util.RemoveEmojiInvisible(tags[j].Name)) + return util.PinYinCompare(tags[i].Name, tags[j].Name) }) case util.SortModeNameDESC: sort.Slice(tags, func(j, i int) bool { - return util.PinYinCompare(util.RemoveEmojiInvisible(tags[i].Name), util.RemoveEmojiInvisible(tags[j].Name)) + return util.PinYinCompare(tags[i].Name, tags[j].Name) }) case util.SortModeAlphanumASC: sort.Slice(tags, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible((tags)[i].Name), util.RemoveEmojiInvisible((tags)[j].Name)) + return util.NaturalCompare((tags)[i].Name, (tags)[j].Name) }) case util.SortModeAlphanumDESC: sort.Slice(tags, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible((tags)[j].Name), util.RemoveEmojiInvisible((tags)[i].Name)) + return util.NaturalCompare((tags)[j].Name, (tags)[i].Name) }) case util.SortModeRefCountASC: sort.Slice(tags, func(i, j int) bool { return (tags)[i].Count < (tags)[j].Count }) @@ -268,7 +267,7 @@ func sortTags(tags Tags) { sort.Slice(tags, func(i, j int) bool { return (tags)[i].Count > (tags)[j].Count }) default: sort.Slice(tags, func(i, j int) bool { - return natsort.Compare(util.RemoveEmojiInvisible((tags)[i].Name), util.RemoveEmojiInvisible((tags)[j].Name)) + return util.NaturalCompare((tags)[i].Name, (tags)[j].Name) }) } } @@ -278,7 +277,7 @@ func SearchTags(keyword string) (ret []string) { defer logging.Recover() // 定位 无法添加题头图标签 https://github.com/siyuan-note/siyuan/issues/6756 labels := labelBlocksByKeyword(keyword) - for label, _ := range labels { + for label := range labels { _, t := search.MarkText(label, keyword, 1024, Conf.Search.CaseSensitive) ret = append(ret, t) } diff --git a/kernel/util/sort.go b/kernel/util/sort.go index 41fdea64d..57c45aedc 100644 --- a/kernel/util/sort.go +++ b/kernel/util/sort.go @@ -21,11 +21,21 @@ import ( "io" "strings" + "github.com/facette/natsort" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" ) +func NaturalCompare(str1, str2 string) bool { + str1 = RemoveEmojiInvisible(str1) + str2 = RemoveEmojiInvisible(str2) + return natsort.Compare(str1, str2) +} + func PinYinCompare(str1, str2 string) bool { + str1 = RemoveEmojiInvisible(str1) + str2 = RemoveEmojiInvisible(str2) + // Doc tree, backlinks, tags and templates ignores case when sorting alphabetically by name https://github.com/siyuan-note/siyuan/issues/8360 str1 = strings.ToLower(str1) str2 = strings.ToLower(str2)