mirror of
https://github.com/siyuan-note/siyuan.git
synced 2025-12-30 13:28:48 +01:00
Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
commit
d601984057
9 changed files with 107 additions and 30 deletions
|
|
@ -94,5 +94,8 @@ func pushTransactions(app, session string, transactions []*model.Transaction) {
|
|||
evt.AppId = app
|
||||
evt.SessionId = session
|
||||
evt.Data = transactions
|
||||
for _, tx := range transactions {
|
||||
tx.WaitForCommit()
|
||||
}
|
||||
util.PushEvent(evt)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -28,10 +28,11 @@ type LayoutTable struct {
|
|||
Spec int `json:"spec"` // 布局格式版本
|
||||
ID string `json:"id"` // 布局 ID
|
||||
|
||||
Columns []*ViewTableColumn `json:"columns"` // 表格列
|
||||
RowIDs []string `json:"rowIds"` // 行 ID,用于自定义排序
|
||||
Filters []*ViewFilter `json:"filters"` // 过滤规则
|
||||
Sorts []*ViewSort `json:"sorts"` // 排序规则
|
||||
Columns []*ViewTableColumn `json:"columns"` // 表格列
|
||||
RowIDs []string `json:"rowIds"` // 行 ID,用于自定义排序
|
||||
Filters []*ViewFilter `json:"filters"` // 过滤规则
|
||||
Sorts []*ViewSort `json:"sorts"` // 排序规则
|
||||
PageSize int `json:"pageSize"` // 每页行数
|
||||
}
|
||||
|
||||
type ViewTableColumn struct {
|
||||
|
|
@ -571,13 +572,14 @@ func (value *Value) CompareOperator(other *Value, operator FilterOperator) bool
|
|||
|
||||
// Table 描述了表格实例的结构。
|
||||
type Table struct {
|
||||
ID string `json:"id"` // 表格布局 ID
|
||||
Icon string `json:"icon"` // 表格图标
|
||||
Name string `json:"name"` // 表格名称
|
||||
Filters []*ViewFilter `json:"filters"` // 过滤规则
|
||||
Sorts []*ViewSort `json:"sorts"` // 排序规则
|
||||
Columns []*TableColumn `json:"columns"` // 表格列
|
||||
Rows []*TableRow `json:"rows"` // 表格行
|
||||
ID string `json:"id"` // 表格布局 ID
|
||||
Icon string `json:"icon"` // 表格图标
|
||||
Name string `json:"name"` // 表格名称
|
||||
Filters []*ViewFilter `json:"filters"` // 过滤规则
|
||||
Sorts []*ViewSort `json:"sorts"` // 排序规则
|
||||
Columns []*TableColumn `json:"columns"` // 表格列
|
||||
Rows []*TableRow `json:"rows"` // 表格行
|
||||
RowCount int `json:"rowCount"` // 表格总行数
|
||||
}
|
||||
|
||||
type TableColumn struct {
|
||||
|
|
|
|||
|
|
@ -50,7 +50,7 @@ require (
|
|||
github.com/rqlite/sql v0.0.0-20221103124402-8f9ff0ceb8f0
|
||||
github.com/sashabaranov/go-openai v1.17.9
|
||||
github.com/shirou/gopsutil/v3 v3.23.11
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208043525-6211184a4438
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208085113-c89895f2a075
|
||||
github.com/siyuan-note/encryption v0.0.0-20220713091850-5ecd92177b75
|
||||
github.com/siyuan-note/eventbus v0.0.0-20230804030110-cf250f838c80
|
||||
github.com/siyuan-note/filelock v0.0.0-20231206081043-b75b363ddb1b
|
||||
|
|
|
|||
|
|
@ -356,8 +356,8 @@ github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFR
|
|||
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d h1:lvCTyBbr36+tqMccdGMwuEU+hjux/zL6xSmf5S9ITaA=
|
||||
github.com/shurcooL/gofontwoff v0.0.0-20181114050219-180f79e6909d/go.mod h1:05UtEgK5zq39gLST6uB0cf3NEHjETfB4Fgr3Gx5R9Vw=
|
||||
github.com/simplereach/timeutils v1.2.0/go.mod h1:VVbQDfN/FHRZa1LSqcwo4kNZ62OOyqLLGQKYB3pB0Q8=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208043525-6211184a4438 h1:MMQYT1Kbrr2kgmwSwJXseCM+CUg5QmWMgFz3xseQIBk=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208043525-6211184a4438/go.mod h1:JFtbncCYIJft4Krp7U8wdxfqmV7DzpVpfBwz/KGUjX4=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208085113-c89895f2a075 h1:AS4npSJSgBXGMR09USiPgdXmeaIJ02p5xFmPZjMNSTs=
|
||||
github.com/siyuan-note/dejavu v0.0.0-20231208085113-c89895f2a075/go.mod h1:JFtbncCYIJft4Krp7U8wdxfqmV7DzpVpfBwz/KGUjX4=
|
||||
github.com/siyuan-note/encryption v0.0.0-20220713091850-5ecd92177b75 h1:Bi7/7f29LW+Fm0cHc0J1NO1cZqyJwljSWVmfOqVZgaE=
|
||||
github.com/siyuan-note/encryption v0.0.0-20220713091850-5ecd92177b75/go.mod h1:H8fyqqAbp9XreANjeSbc72zEdFfKTXYN34tc1TjZwtw=
|
||||
github.com/siyuan-note/eventbus v0.0.0-20230804030110-cf250f838c80 h1:XghjHKJd+SiL0DkGYFVC+UGUDFtnR4v9gkAbPeh9Eq8=
|
||||
|
|
|
|||
|
|
@ -622,6 +622,8 @@ func renderAttributeViewTable(attrView *av.AttributeView, view *av.View, page, p
|
|||
return iv < jv
|
||||
})
|
||||
|
||||
// 分页
|
||||
ret.RowCount = len(ret.Rows)
|
||||
if 0 < pageSize {
|
||||
start := (page - 1) * pageSize
|
||||
end := start + pageSize
|
||||
|
|
@ -959,6 +961,34 @@ func setAttributeViewSorts(operation *Operation) (err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (tx *Transaction) doSetAttrViewPageSize(operation *Operation) (ret *TxErr) {
|
||||
err := setAttributeViewPageSize(operation)
|
||||
if nil != err {
|
||||
return &TxErr{code: TxErrWriteAttributeView, id: operation.AvID, msg: err.Error()}
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func setAttributeViewPageSize(operation *Operation) (err error) {
|
||||
attrView, err := av.ParseAttributeView(operation.AvID)
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
view, err := attrView.GetCurrentView()
|
||||
if nil != err {
|
||||
return
|
||||
}
|
||||
|
||||
switch view.LayoutType {
|
||||
case av.LayoutTypeTable:
|
||||
view.Table.PageSize = int(operation.Data.(float64))
|
||||
}
|
||||
|
||||
err = av.SaveAttributeView(attrView)
|
||||
return
|
||||
}
|
||||
|
||||
func (tx *Transaction) doSetAttrViewColCalc(operation *Operation) (ret *TxErr) {
|
||||
err := setAttributeViewColumnCalc(operation)
|
||||
if nil != err {
|
||||
|
|
|
|||
|
|
@ -17,6 +17,8 @@ import (
|
|||
)
|
||||
|
||||
func OCRAssetsJob() {
|
||||
util.WaitForTesseractInit()
|
||||
|
||||
if !util.TesseractEnabled {
|
||||
return
|
||||
}
|
||||
|
|
@ -25,6 +27,10 @@ func OCRAssetsJob() {
|
|||
}
|
||||
|
||||
func autoOCRAssets() {
|
||||
if !util.TesseractEnabled {
|
||||
return
|
||||
}
|
||||
|
||||
defer logging.Recover()
|
||||
|
||||
assetsPath := util.GetDataAssetsAbsPath()
|
||||
|
|
@ -38,7 +44,7 @@ func autoOCRAssets() {
|
|||
util.AssetsTexts[p] = text
|
||||
util.AssetsTextsLock.Unlock()
|
||||
if "" != text {
|
||||
util.AssetsTextsChanged = true
|
||||
util.AssetsTextsChanged.Store(true)
|
||||
}
|
||||
if 7 <= i { // 一次任务中最多处理 7 张图片,防止长时间占用系统资源
|
||||
break
|
||||
|
|
@ -65,7 +71,7 @@ func cleanNotExistAssetsTexts() {
|
|||
|
||||
for _, asset := range toRemoves {
|
||||
delete(util.AssetsTexts, asset)
|
||||
util.AssetsTextsChanged = true
|
||||
util.AssetsTextsChanged.Store(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -128,7 +134,7 @@ func LoadAssetsTexts() {
|
|||
}
|
||||
|
||||
func SaveAssetsTexts() {
|
||||
if !util.AssetsTextsChanged {
|
||||
if !util.AssetsTextsChanged.Load() {
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -154,5 +160,5 @@ func SaveAssetsTexts() {
|
|||
logging.LogWarnf("save assets texts [size=%s] to [%s], elapsed [%.2fs]", humanize.Bytes(uint64(len(data))), assetsTextsPath, elapsed)
|
||||
}
|
||||
|
||||
util.AssetsTextsChanged = false
|
||||
util.AssetsTextsChanged.Store(false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -163,11 +163,11 @@ func SyncData(byHand bool) {
|
|||
|
||||
func lockSync() {
|
||||
syncLock.Lock()
|
||||
isSyncing = true
|
||||
isSyncing.Store(true)
|
||||
}
|
||||
|
||||
func unlockSync() {
|
||||
isSyncing = false
|
||||
isSyncing.Store(false)
|
||||
syncLock.Unlock()
|
||||
}
|
||||
|
||||
|
|
@ -178,15 +178,15 @@ func syncData(exit, byHand bool) {
|
|||
return
|
||||
}
|
||||
|
||||
lockSync()
|
||||
defer unlockSync()
|
||||
|
||||
util.BroadcastByType("main", "syncing", 0, Conf.Language(81), nil)
|
||||
if !exit && !isProviderOnline(byHand) { // 这个操作比较耗时,所以要先推送 syncing 事件后再判断网络,这样才能给用户更即时的反馈
|
||||
util.BroadcastByType("main", "syncing", 2, Conf.Language(28), nil)
|
||||
return
|
||||
}
|
||||
|
||||
lockSync()
|
||||
defer unlockSync()
|
||||
|
||||
if exit {
|
||||
ExitSyncSucc = 0
|
||||
logging.LogInfof("sync before exit")
|
||||
|
|
@ -256,7 +256,7 @@ func checkSync(boot, exit, byHand bool) bool {
|
|||
}
|
||||
}
|
||||
|
||||
if isSyncing {
|
||||
if isSyncing.Load() {
|
||||
logging.LogWarnf("sync is in progress")
|
||||
planSyncAfter(fixSyncInterval)
|
||||
return false
|
||||
|
|
@ -431,7 +431,7 @@ func SetSyncProviderWebDAV(webdav *conf.WebDAV) (err error) {
|
|||
|
||||
var (
|
||||
syncLock = sync.Mutex{}
|
||||
isSyncing bool
|
||||
isSyncing = atomic.Bool{}
|
||||
)
|
||||
|
||||
func CreateCloudSyncDir(name string) (err error) {
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import (
|
|||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
|
|
@ -128,6 +129,7 @@ func flushTx(tx *Transaction) {
|
|||
|
||||
func PerformTransactions(transactions *[]*Transaction) {
|
||||
for _, tx := range *transactions {
|
||||
tx.m = &sync.Mutex{}
|
||||
txQueue <- tx
|
||||
}
|
||||
return
|
||||
|
|
@ -202,6 +204,8 @@ func performTx(tx *Transaction) (ret *TxErr) {
|
|||
ret = tx.doSetAttrViewFilters(op)
|
||||
case "setAttrViewSorts":
|
||||
ret = tx.doSetAttrViewSorts(op)
|
||||
case "setAttrViewPageSize":
|
||||
ret = tx.doSetAttrViewPageSize(op)
|
||||
case "setAttrViewColWidth":
|
||||
ret = tx.doSetAttrViewColumnWidth(op)
|
||||
case "setAttrViewColWrap":
|
||||
|
|
@ -1168,8 +1172,6 @@ type Operation struct {
|
|||
Format string `json:"format"` // 属性视图列格式化
|
||||
KeyID string `json:"keyID"` // 属性视列 ID
|
||||
RowID string `json:"rowID"` // 属性视图行 ID
|
||||
|
||||
discard bool // 用于标识是否在事务合并中丢弃
|
||||
}
|
||||
|
||||
type Transaction struct {
|
||||
|
|
@ -1181,6 +1183,18 @@ type Transaction struct {
|
|||
nodes map[string]*ast.Node
|
||||
|
||||
luteEngine *lute.Lute
|
||||
m *sync.Mutex
|
||||
state atomic.Int32 // 0: 未提交,1: 已提交,2: 已回滚
|
||||
}
|
||||
|
||||
func (tx *Transaction) WaitForCommit() {
|
||||
for {
|
||||
if 0 == tx.state.Load() {
|
||||
time.Sleep(10 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (tx *Transaction) begin() (err error) {
|
||||
|
|
@ -1190,6 +1204,8 @@ func (tx *Transaction) begin() (err error) {
|
|||
tx.trees = map[string]*parse.Tree{}
|
||||
tx.nodes = map[string]*ast.Node{}
|
||||
tx.luteEngine = util.NewLute()
|
||||
tx.m.Lock()
|
||||
tx.state.Store(0)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -1202,11 +1218,15 @@ func (tx *Transaction) commit() (err error) {
|
|||
refreshDynamicRefTexts(tx.nodes, tx.trees)
|
||||
IncSync()
|
||||
tx.trees = nil
|
||||
tx.state.Store(1)
|
||||
tx.m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
func (tx *Transaction) rollback() {
|
||||
tx.trees, tx.nodes = nil, nil
|
||||
tx.state.Store(2)
|
||||
tx.m.Unlock()
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/88250/gulu"
|
||||
|
|
@ -40,7 +41,7 @@ var (
|
|||
TesseractMaxSize = 2 * 1000 * uint64(1000)
|
||||
AssetsTexts = map[string]string{}
|
||||
AssetsTextsLock = sync.Mutex{}
|
||||
AssetsTextsChanged = false
|
||||
AssetsTextsChanged = atomic.Bool{}
|
||||
|
||||
TesseractLangs []string
|
||||
)
|
||||
|
|
@ -49,7 +50,7 @@ func SetAssetText(asset, text string) {
|
|||
AssetsTextsLock.Lock()
|
||||
AssetsTexts[asset] = text
|
||||
AssetsTextsLock.Unlock()
|
||||
AssetsTextsChanged = true
|
||||
AssetsTextsChanged.Store(true)
|
||||
}
|
||||
|
||||
func ExistsAssetText(asset string) (ret bool) {
|
||||
|
|
@ -75,7 +76,7 @@ func GetAssetText(asset string, force bool) (ret string) {
|
|||
AssetsTexts[asset] = ret
|
||||
AssetsTextsLock.Unlock()
|
||||
if "" != ret {
|
||||
AssetsTextsChanged = true
|
||||
AssetsTextsChanged.Store(true)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
|
@ -136,9 +137,21 @@ func Tesseract(imgAbsPath string) string {
|
|||
return ret
|
||||
}
|
||||
|
||||
var tesseractInited = atomic.Bool{}
|
||||
|
||||
func WaitForTesseractInit() {
|
||||
for {
|
||||
if tesseractInited.Load() {
|
||||
return
|
||||
}
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func InitTesseract() {
|
||||
ver := getTesseractVer()
|
||||
if "" == ver {
|
||||
tesseractInited.Store(true)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -146,6 +159,7 @@ func InitTesseract() {
|
|||
if 1 > len(langs) {
|
||||
logging.LogWarnf("no tesseract langs found")
|
||||
TesseractEnabled = false
|
||||
tesseractInited.Store(true)
|
||||
return
|
||||
}
|
||||
|
||||
|
|
@ -162,6 +176,7 @@ func InitTesseract() {
|
|||
TesseractEnabled = enabledBool
|
||||
if !enabledBool {
|
||||
logging.LogInfof("tesseract-ocr disabled by env")
|
||||
tesseractInited.Store(true)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
@ -169,6 +184,7 @@ func InitTesseract() {
|
|||
|
||||
TesseractLangs = filterTesseractLangs(langs)
|
||||
logging.LogInfof("tesseract-ocr enabled [ver=%s, maxSize=%s, langs=%s]", ver, humanize.Bytes(TesseractMaxSize), strings.Join(TesseractLangs, "+"))
|
||||
tesseractInited.Store(true)
|
||||
}
|
||||
|
||||
func filterTesseractLangs(langs []string) (ret []string) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue