From 07ec3183560fdac3b2bcb88362ddda79c321d3c8 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 09:37:08 +0800 Subject: [PATCH 1/6] :bug: https://github.com/siyuan-note/siyuan/issues/10035 --- kernel/bazaar/package.go | 7 +------ kernel/model/bazzar.go | 4 ++++ 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/kernel/bazaar/package.go b/kernel/bazaar/package.go index 9c238f3d4..5720e31c5 100644 --- a/kernel/bazaar/package.go +++ b/kernel/bazaar/package.go @@ -656,16 +656,11 @@ func getBazaarIndex() map[string]*bazaarPackage { const defaultMinAppVersion = "2.9.0" func disallowDisplayBazaarPackage(pkg *Package) bool { - if "" == pkg.MinAppVersion { // 目前暂时放过所有不带 minAppVersion 的集市包,后续版本会使用 defaultMinAppVersion + if "" == pkg.MinAppVersion { // TODO: 目前暂时放过所有不带 minAppVersion 的集市包,后续版本会使用 defaultMinAppVersion return false } if 0 < semver.Compare("v"+pkg.MinAppVersion, "v"+util.Ver) { return true } - - if 0 < len(pkg.Backends) { - - } - return false } diff --git a/kernel/model/bazzar.go b/kernel/model/bazzar.go index 7bcb7f8f9..623f9b410 100644 --- a/kernel/model/bazzar.go +++ b/kernel/model/bazzar.go @@ -350,6 +350,10 @@ func matchPackage(keywords []string, pkg *bazaar.Package) bool { return true } + if nil == pkg { + return false + } + for _, keyword := range keywords { if strings.Contains(strings.ToLower(pkg.DisplayName.Default), keyword) || strings.Contains(strings.ToLower(pkg.DisplayName.ZhCN), keyword) || From 00e99b23b740e12b73ef83c830ce6ab52c495887 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 09:38:12 +0800 Subject: [PATCH 2/6] :bug: https://github.com/siyuan-note/siyuan/issues/10035 --- kernel/model/bazzar.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/model/bazzar.go b/kernel/model/bazzar.go index 623f9b410..dda24cdb8 100644 --- a/kernel/model/bazzar.go +++ b/kernel/model/bazzar.go @@ -350,7 +350,7 @@ func matchPackage(keywords []string, pkg *bazaar.Package) bool { return true } - if nil == pkg { + if nil == pkg || nil == pkg.DisplayName || nil == pkg.Description { return false } From 89158e77e283a19fee6976cdf8b47936942a7c4d Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 09:51:44 +0800 Subject: [PATCH 3/6] :art: Add Rollup column to database table view https://github.com/siyuan-note/siyuan/issues/9958 --- kernel/model/attribute_view.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index 29f3aca01..cada7e4dd 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -252,7 +252,7 @@ func GetBlockAttributeViewKeys(blockID string) (ret []*BlockAttributeViewKeys) { destVal.Number.FormatNumber() } - kv.Values[0].Rollup.Contents = append(kv.Values[0].Rollup.Contents, destAv.GetValue(kv.Key.Rollup.KeyID, bID).String()) + kv.Values[0].Rollup.Contents = append(kv.Values[0].Rollup.Contents, destVal.String()) } kv.Values[0].Rollup.RenderContents(kv.Key.Rollup.Calc) From 2d6900eafa9f7e71ce65a6e0c362286612d7a365 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 10:30:39 +0800 Subject: [PATCH 4/6] :art: Add Rollup column to database table view https://github.com/siyuan-note/siyuan/issues/9958 --- kernel/av/relation.go | 102 +++++++++++++++++++++++++++++++++ kernel/model/attribute_view.go | 98 ++++++++++++++++++++----------- 2 files changed, 165 insertions(+), 35 deletions(-) create mode 100644 kernel/av/relation.go diff --git a/kernel/av/relation.go b/kernel/av/relation.go new file mode 100644 index 000000000..f841a1ab2 --- /dev/null +++ b/kernel/av/relation.go @@ -0,0 +1,102 @@ +package av + +import ( + "os" + "path/filepath" + "sync" + + "github.com/88250/gulu" + "github.com/siyuan-note/filelock" + "github.com/siyuan-note/logging" + "github.com/siyuan-note/siyuan/kernel/util" + "github.com/vmihailenco/msgpack/v5" +) + +var ( + attributeViewRelationsLock = sync.Mutex{} +) + +func RemoveAvRel(avID, destAvID string) { + attributeViewRelationsLock.Lock() + defer attributeViewRelationsLock.Unlock() + + relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack") + if !filelock.IsExist(relations) { + return + } + + data, err := filelock.ReadFile(relations) + if nil != err { + logging.LogErrorf("read attribute view relations failed: %s", err) + return + } + + avRels := map[string][]string{} + if err = msgpack.Unmarshal(data, &avRels); nil != err { + logging.LogErrorf("unmarshal attribute view relations failed: %s", err) + return + } + + destAvIDs := avRels[avID] + if nil == destAvIDs { + return + } + + var newAvIDs []string + for _, v := range destAvIDs { + if v != destAvID { + newAvIDs = append(newAvIDs, v) + } + } + avRels[avID] = newAvIDs + + data, err = msgpack.Marshal(avRels) + if nil != err { + logging.LogErrorf("marshal attribute view relations failed: %s", err) + return + } + if err = filelock.WriteFile(relations, data); nil != err { + logging.LogErrorf("write attribute view relations failed: %s", err) + return + } +} + +func UpsertAvRel(avID, destAvID string) { + attributeViewRelationsLock.Lock() + defer attributeViewRelationsLock.Unlock() + + avRelations := map[string][]string{} + relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack") + if !filelock.IsExist(relations) { + if err := os.MkdirAll(filepath.Dir(relations), 0755); nil != err { + logging.LogErrorf("create attribute view dir failed: %s", err) + return + } + } else { + data, err := filelock.ReadFile(relations) + if nil != err { + logging.LogErrorf("read attribute view relations failed: %s", err) + return + } + + if err = msgpack.Unmarshal(data, &avRelations); nil != err { + logging.LogErrorf("unmarshal attribute view relations failed: %s", err) + return + } + } + + destAvIDs := avRelations[avID] + destAvIDs = append(destAvIDs, destAvID) + destAvIDs = gulu.Str.RemoveDuplicatedElem(destAvIDs) + avRelations[avID] = destAvIDs + + data, err := msgpack.Marshal(avRelations) + if nil != err { + logging.LogErrorf("marshal attribute view relations failed: %s", err) + return + } + if err = filelock.WriteFile(relations, data); nil != err { + logging.LogErrorf("write attribute view relations failed: %s", err) + return + } +} diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index cada7e4dd..cdb392517 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -980,27 +980,31 @@ func updateAttributeViewColRelation(operation *Operation) (err error) { srcRel := keyValues.Key.Relation // 已经设置过双向关联的话需要先断开双向关联 - if nil != srcRel && srcRel.IsTwoWay { - oldDestAv, _ := av.ParseAttributeView(srcRel.AvID) - if nil != oldDestAv { - isOldSameAv := oldDestAv.ID == destAv.ID - if isOldSameAv { - oldDestAv = destAv - } + if nil != srcRel { + if srcRel.IsTwoWay { + oldDestAv, _ := av.ParseAttributeView(srcRel.AvID) + if nil != oldDestAv { + isOldSameAv := oldDestAv.ID == destAv.ID + if isOldSameAv { + oldDestAv = destAv + } - oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID) - if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay { - oldDestKey.Relation.IsTwoWay = false - oldDestKey.Relation.BackKeyID = "" - } + oldDestKey, _ := oldDestAv.GetKey(srcRel.BackKeyID) + if nil != oldDestKey && nil != oldDestKey.Relation && oldDestKey.Relation.AvID == srcAv.ID && oldDestKey.Relation.IsTwoWay { + oldDestKey.Relation.IsTwoWay = false + oldDestKey.Relation.BackKeyID = "" + } - if !isOldSameAv { - err = av.SaveAttributeView(oldDestAv) - if nil != err { - return + if !isOldSameAv { + err = av.SaveAttributeView(oldDestAv) + if nil != err { + return + } } } } + + av.RemoveAvRel(srcAv.ID, srcRel.AvID) } srcRel = &av.Relation{ @@ -1069,6 +1073,8 @@ func updateAttributeViewColRelation(operation *Operation) (err error) { err = av.SaveAttributeView(destAv) util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID}) } + + av.UpsertAvRel(srcAv.ID, destAv.ID) return } @@ -2116,31 +2122,53 @@ func removeAttributeViewColumn(operation *Operation) (err error) { } } - // 删除双向关联的目标列 - if nil != removedKey && nil != removedKey.Relation && removedKey.Relation.IsTwoWay { - destAv, _ := av.ParseAttributeView(removedKey.Relation.AvID) - if nil != destAv { - for i, keyValues := range destAv.KeyValues { - if keyValues.Key.ID == removedKey.Relation.BackKeyID { - destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...) - break - } - } + if nil != removedKey && av.KeyTypeRelation == removedKey.Type && nil != removedKey.Relation { + if removedKey.Relation.IsTwoWay { + // 删除双向关联的目标列 - for _, view := range destAv.Views { - switch view.LayoutType { - case av.LayoutTypeTable: - for i, column := range view.Table.Columns { - if column.ID == removedKey.Relation.BackKeyID { - view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...) - break + destAv, _ := av.ParseAttributeView(removedKey.Relation.AvID) + if nil != destAv { + destAvRelSrcAv := false + for i, keyValues := range destAv.KeyValues { + if keyValues.Key.ID == removedKey.Relation.BackKeyID { + destAv.KeyValues = append(destAv.KeyValues[:i], destAv.KeyValues[i+1:]...) + continue + } + + if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == attrView.ID { + destAvRelSrcAv = true + } + } + + for _, view := range destAv.Views { + switch view.LayoutType { + case av.LayoutTypeTable: + for i, column := range view.Table.Columns { + if column.ID == removedKey.Relation.BackKeyID { + view.Table.Columns = append(view.Table.Columns[:i], view.Table.Columns[i+1:]...) + break + } } } } + + av.SaveAttributeView(destAv) + util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID}) + + if !destAvRelSrcAv { + av.RemoveAvRel(destAv.ID, attrView.ID) + } } - av.SaveAttributeView(destAv) - util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID}) + srcAvRelDestAv := false + for _, keyValues := range attrView.KeyValues { + if av.KeyTypeRelation == keyValues.Key.Type && keyValues.Key.Relation.AvID == removedKey.Relation.AvID { + srcAvRelDestAv = true + } + } + if !srcAvRelDestAv { + av.RemoveAvRel(attrView.ID, removedKey.Relation.AvID) + } } } From 290df47a1e381b040cda02e3e34893caef55ab24 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 10:58:40 +0800 Subject: [PATCH 5/6] :art: Add Rollup column to database table view https://github.com/siyuan-note/siyuan/issues/9958 --- kernel/av/relation.go | 50 ++++++++++++---- kernel/model/attribute_view.go | 104 +++++++++++++++++++-------------- 2 files changed, 98 insertions(+), 56 deletions(-) diff --git a/kernel/av/relation.go b/kernel/av/relation.go index f841a1ab2..28a4eb1f3 100644 --- a/kernel/av/relation.go +++ b/kernel/av/relation.go @@ -16,7 +16,35 @@ var ( attributeViewRelationsLock = sync.Mutex{} ) -func RemoveAvRel(avID, destAvID string) { +func GetSrcAvIDs(destAvID string) []string { + attributeViewRelationsLock.Lock() + defer attributeViewRelationsLock.Unlock() + + relations := filepath.Join(util.DataDir, "storage", "av", "relations.msgpack") + if !filelock.IsExist(relations) { + return nil + } + + data, err := filelock.ReadFile(relations) + if nil != err { + logging.LogErrorf("read attribute view relations failed: %s", err) + return nil + } + + avRels := map[string][]string{} + if err = msgpack.Unmarshal(data, &avRels); nil != err { + logging.LogErrorf("unmarshal attribute view relations failed: %s", err) + return nil + } + + srcAvIDs := avRels[destAvID] + if nil == srcAvIDs { + return nil + } + return srcAvIDs +} + +func RemoveAvRel(srcAvID, destAvID string) { attributeViewRelationsLock.Lock() defer attributeViewRelationsLock.Unlock() @@ -37,18 +65,18 @@ func RemoveAvRel(avID, destAvID string) { return } - destAvIDs := avRels[avID] - if nil == destAvIDs { + srcAvIDs := avRels[destAvID] + if nil == srcAvIDs { return } var newAvIDs []string - for _, v := range destAvIDs { - if v != destAvID { + for _, v := range srcAvIDs { + if v != srcAvID { newAvIDs = append(newAvIDs, v) } } - avRels[avID] = newAvIDs + avRels[destAvID] = newAvIDs data, err = msgpack.Marshal(avRels) if nil != err { @@ -61,7 +89,7 @@ func RemoveAvRel(avID, destAvID string) { } } -func UpsertAvRel(avID, destAvID string) { +func UpsertAvBackRel(srcAvID, destAvID string) { attributeViewRelationsLock.Lock() defer attributeViewRelationsLock.Unlock() @@ -85,10 +113,10 @@ func UpsertAvRel(avID, destAvID string) { } } - destAvIDs := avRelations[avID] - destAvIDs = append(destAvIDs, destAvID) - destAvIDs = gulu.Str.RemoveDuplicatedElem(destAvIDs) - avRelations[avID] = destAvIDs + srcAvIDs := avRelations[destAvID] + srcAvIDs = append(srcAvIDs, srcAvID) + srcAvIDs = gulu.Str.RemoveDuplicatedElem(srcAvIDs) + avRelations[destAvID] = srcAvIDs data, err := msgpack.Marshal(avRelations) if nil != err { diff --git a/kernel/model/attribute_view.go b/kernel/model/attribute_view.go index cdb392517..a2de70a76 100644 --- a/kernel/model/attribute_view.go +++ b/kernel/model/attribute_view.go @@ -693,6 +693,14 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View) (ret *a } rows[val.BlockID] = values } + + // 数据订正,补全关联 + if av.KeyTypeRelation == keyValues.Key.Type && nil != keyValues.Key.Relation { + av.UpsertAvBackRel(attrView.ID, keyValues.Key.Relation.AvID) + if keyValues.Key.Relation.IsTwoWay { + av.UpsertAvBackRel(keyValues.Key.Relation.AvID, attrView.ID) + } + } } // 过滤掉不存在的行 @@ -1074,7 +1082,7 @@ func updateAttributeViewColRelation(operation *Operation) (err error) { util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID}) } - av.UpsertAvRel(srcAv.ID, destAv.ID) + av.UpsertAvBackRel(srcAv.ID, destAv.ID) return } @@ -2332,7 +2340,7 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string, // 关联列得 content 是自动渲染的,所以不需要保存 val.Relation.Contents = nil - // 计算关联排序模式 + // 计算关联变更模式 if len(oldRelationBlockIDs) == len(val.Relation.BlockIDs) { relationChangeMode = 0 } else { @@ -2377,64 +2385,70 @@ func UpdateAttributeViewCell(tx *Transaction, avID, keyID, rowID, cellID string, } key, _ := attrView.GetKey(val.KeyID) - if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation && key.Relation.IsTwoWay { + if nil != key && av.KeyTypeRelation == key.Type && nil != key.Relation { destAv, _ := av.ParseAttributeView(key.Relation.AvID) if nil != destAv { - // relationChangeMode - // 0:关联列值不变(仅排序),不影响目标值 - // 1:关联列值增加,增加目标值 - // 2:关联列值减少,减少目标值 + if key.Relation.IsTwoWay { + // relationChangeMode + // 0:关联列值不变(仅排序),不影响目标值 + // 1:关联列值增加,增加目标值 + // 2:关联列值减少,减少目标值 - if 1 == relationChangeMode { - addBlockIDs := val.Relation.BlockIDs - for _, bID := range oldRelationBlockIDs { - addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID) - } - - for _, blockID := range addBlockIDs { - for _, keyValues := range destAv.KeyValues { - if keyValues.Key.ID != key.Relation.BackKeyID { - continue - } - - destVal := keyValues.GetValue(blockID) - if nil == destVal { - destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}} - keyValues.Values = append(keyValues.Values, destVal) - } - - destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID) - destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs) - break + if 1 == relationChangeMode { + addBlockIDs := val.Relation.BlockIDs + for _, bID := range oldRelationBlockIDs { + addBlockIDs = gulu.Str.RemoveElem(addBlockIDs, bID) } - } - } else if 2 == relationChangeMode { - removeBlockIDs := oldRelationBlockIDs - for _, bID := range val.Relation.BlockIDs { - removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID) - } - for _, blockID := range removeBlockIDs { - for _, keyValues := range destAv.KeyValues { - if keyValues.Key.ID != key.Relation.BackKeyID { - continue + for _, blockID := range addBlockIDs { + for _, keyValues := range destAv.KeyValues { + if keyValues.Key.ID != key.Relation.BackKeyID { + continue + } + + destVal := keyValues.GetValue(blockID) + if nil == destVal { + destVal = &av.Value{ID: ast.NewNodeID(), KeyID: keyValues.Key.ID, BlockID: blockID, Type: keyValues.Key.Type, Relation: &av.ValueRelation{}} + keyValues.Values = append(keyValues.Values, destVal) + } + + destVal.Relation.BlockIDs = append(destVal.Relation.BlockIDs, rowID) + destVal.Relation.BlockIDs = gulu.Str.RemoveDuplicatedElem(destVal.Relation.BlockIDs) + break } + } + } else if 2 == relationChangeMode { + removeBlockIDs := oldRelationBlockIDs + for _, bID := range val.Relation.BlockIDs { + removeBlockIDs = gulu.Str.RemoveElem(removeBlockIDs, bID) + } - for _, value := range keyValues.Values { - if value.BlockID == blockID { - value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID) - break + for _, blockID := range removeBlockIDs { + for _, keyValues := range destAv.KeyValues { + if keyValues.Key.ID != key.Relation.BackKeyID { + continue + } + + for _, value := range keyValues.Values { + if value.BlockID == blockID { + value.Relation.BlockIDs = gulu.Str.RemoveElem(value.Relation.BlockIDs, rowID) + break + } } } } } - } - av.SaveAttributeView(destAv) - util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": destAv.ID}) + av.SaveAttributeView(destAv) + } } } + relatedAvIDs := av.GetSrcAvIDs(avID) + for _, relatedAvID := range relatedAvIDs { + util.BroadcastByType("protyle", "refreshAttributeView", 0, "", map[string]interface{}{"id": relatedAvID}) + } + if err = av.SaveAttributeView(attrView); nil != err { return } From 05d56359d16ba64f78f9947625bffb6f7a2af632 Mon Sep 17 00:00:00 2001 From: Daniel <845765@qq.com> Date: Sun, 31 Dec 2023 11:10:51 +0800 Subject: [PATCH 6/6] :memo: Update copyright year --- app/electron-builder-darwin-arm64.yml | 2 +- app/electron-builder-darwin.yml | 2 +- app/electron-builder-linux.yml | 2 +- app/electron-builder.yml | 2 +- kernel/versioninfo.json | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/electron-builder-darwin-arm64.yml b/app/electron-builder-darwin-arm64.yml index fcf164d1b..e4db7376e 100644 --- a/app/electron-builder-darwin-arm64.yml +++ b/app/electron-builder-darwin-arm64.yml @@ -2,7 +2,7 @@ productName: "SiYuan" appId: "org.b3log.siyuan" asar: false compression: "normal" -copyright: "© 2023 Yunnan Liandi Technology Co., Ltd." +copyright: "© 2024 Yunnan Liandi Technology Co., Ltd." artifactName: "siyuan-${version}-${os}-arm64.${ext}" extraMetadata: main: "electron/main.js" diff --git a/app/electron-builder-darwin.yml b/app/electron-builder-darwin.yml index 36265162f..6b6459ee6 100644 --- a/app/electron-builder-darwin.yml +++ b/app/electron-builder-darwin.yml @@ -2,7 +2,7 @@ productName: "SiYuan" appId: "org.b3log.siyuan" asar: false compression: "normal" -copyright: "© 2023 Yunnan Liandi Technology Co., Ltd." +copyright: "© 2024 Yunnan Liandi Technology Co., Ltd." artifactName: "siyuan-${version}-${os}.${ext}" extraMetadata: main: "electron/main.js" diff --git a/app/electron-builder-linux.yml b/app/electron-builder-linux.yml index f8824082e..76031879a 100644 --- a/app/electron-builder-linux.yml +++ b/app/electron-builder-linux.yml @@ -2,7 +2,7 @@ productName: "SiYuan" appId: "org.b3log.siyuan" asar: false compression: "normal" -copyright: "© 2023 Yunnan Liandi Technology Co., Ltd." +copyright: "© 2024 Yunnan Liandi Technology Co., Ltd." artifactName: "siyuan-${version}-${os}.${ext}" extraMetadata: main: "electron/main.js" diff --git a/app/electron-builder.yml b/app/electron-builder.yml index 7fb35c81c..76fcfad4b 100644 --- a/app/electron-builder.yml +++ b/app/electron-builder.yml @@ -2,7 +2,7 @@ productName: "SiYuan" appId: "org.b3log.siyuan" asar: false compression: "normal" -copyright: "© 2023 Yunnan Liandi Technology Co., Ltd." +copyright: "© 2024 Yunnan Liandi Technology Co., Ltd." artifactName: "siyuan-${version}-${os}.${ext}" extraMetadata: main: "electron/main.js" diff --git a/kernel/versioninfo.json b/kernel/versioninfo.json index b5bb075ca..8ed9fc31c 100644 --- a/kernel/versioninfo.json +++ b/kernel/versioninfo.json @@ -12,7 +12,7 @@ "FileDescription": "SiYuan Kernel", "FileVersion": "", "InternalName": "", - "LegalCopyright": "© 2023 Yunnan Liandi Technology Co., Ltd.", + "LegalCopyright": "© 2024 Yunnan Liandi Technology Co., Ltd.", "LegalTrademarks": "", "OriginalFilename": "", "PrivateBuild": "",