Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Vanessa 2023-03-19 23:30:39 +08:00
commit 7ad5cdd067
31 changed files with 155 additions and 249 deletions

View file

@ -507,9 +507,6 @@
"useDefault": "Open with default program",
"previous": "Previous",
"next": "Next",
"lockFile0": "Unable to access data",
"lockFile1": "The data file has been locked by another program",
"lockFile2": "If the problem still occurs frequently in subsequent use, please report it via <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">GitHub Issues</a>",
"kernelFault0": "Kernel connection interrupted...",
"kernelFault1": "Please check if the network connection and kernel process is normal",
"kernelFault2": "If the problem still occurs after restarting, please report it via <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">GitHub Issues</a>",

View file

@ -507,9 +507,6 @@
"useDefault": "Abrir con el programa por defecto",
"previous": "Anterior",
"next": "Siguiente",
"lockFile0": "No se puede acceder a los datos",
"lockFile1": "El archivo de datos ha sido bloqueado por otro programa",
"lockFile2": "Si el problema sigue ocurriendo con frecuencia en el uso posterior, infórmelo a través de <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">Problemas en GitHub</a>",
"kernelFault0": "Conexión del kernel interrumpida...",
"kernelFault1": "Verifique si la conexión de red y los procesos del kernel son normales",
"kernelFault2": "Si el problema sigue produciéndose después de reiniciar, comuníquelo a través de <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">Problemas en GitHub</a>",

View file

@ -507,9 +507,6 @@
"useDefault": "Ouvrir avec le programme par défaut",
"previous": "Précédent",
"next": "Prochain",
"lockFile0": "Impossible d'accéder aux données",
"lockFile1": "Le fichier de données a été verrouillé par un autre programme",
"lockFile2": "Si le problème se produit encore fréquemment lors d'une utilisation ultérieure, veuillez le signaler via <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">GitHub Issues</a>",
"kernelFault0": "Connexion au noyau interrompue...",
"kernelFault1": "Veuillez vérifier si la connexion réseau et les processus du noyau sont normaux",
"kernelFault2": "Si le problème persiste après le redémarrage, veuillez le signaler via <a href=\"https://github.com/siyuan-note/siyuan/issues\" target=\"_blank\">GitHub Issues</a>",

View file

@ -507,9 +507,6 @@
"useDefault": "使用預設程式打開",
"previous": "上一個",
"next": "下一個",
"lockFile0": "無法存取資料",
"lockFile1": "資料檔案已被其他程式鎖定",
"lockFile2": "如果後續使用仍然頻繁出現該問題,請通過<a href=\"https://ld246.com/article/1649901726096\" target=\"_blank\">這裡回饋</a>",
"kernelFault0": "kernel連接中斷...",
"kernelFault1": "請檢查網絡連接和內核進程是否正常",
"kernelFault2": "如果重啟後仍然出現該問題,請通過<a href=\"https://ld246.com/article/1649901726096\" target=\"_blank\">這裡回饋</a>",

View file

@ -507,9 +507,6 @@
"useDefault": "使用默认程序打开",
"previous": "上一个",
"next": "下一个",
"lockFile0": "无法存取数据",
"lockFile1": "数据文件已被其他程序锁定",
"lockFile2": "如果后续使用仍然频繁出现该问题,请通过<a href=\"https://ld246.com/article/1649901726096\" target=\"_blank\">这里反馈</a>",
"kernelFault0": "内核连接中断...",
"kernelFault1": "请检查网络连接和内核进程是否正常",
"kernelFault2": "如果重启后仍然出现该问题,请通过<a href=\"https://ld246.com/article/1649901726096\" target=\"_blank\">这里反馈</a>",

View file

@ -36,7 +36,9 @@ nsis:
createStartMenuShortcut: true
shortcutName: "SiYuan"
license: "../LICENSE"
include: "installer.nsh"
include: "nsis/installer.nsh"
installerSidebar: "nsis/installerSidebar.bmp"
uninstallerSidebar: "nsis/uninstallerSidebar.bmp"
extraResources:
- from: "appearance/boot"

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 151 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -10,7 +10,6 @@ import {openNewWindowById} from "../window/openNewWindow";
/// #endif
import {disabledProtyle} from "../protyle/util/onGet";
import {fetchPost} from "../util/fetch";
import {lockFile} from "../dialog/processSystem";
import {showMessage} from "../dialog/message";
export class BlockPanel {
@ -245,11 +244,6 @@ export class BlockPanel {
private initProtyle(editorElement: HTMLElement) {
const index = parseInt(editorElement.getAttribute("data-index"));
fetchPost("api/block/getBlockInfo", {id: this.nodeIds[index]}, (response) => {
if (response.code === 2) {
// 文件被锁定
lockFile(response.data);
return false;
}
if (response.code === 3) {
showMessage(response.msg);
return;

View file

@ -1,7 +1,6 @@
import {Constants} from "../constants";
import {fetchPost} from "../util/fetch";
/// #if !MOBILE
import {getAllModels} from "../layout/getAll";
import {exportLayout} from "../layout/util";
/// #endif
/// #if !BROWSER
@ -29,47 +28,6 @@ export const lockScreen = () => {
/// #endif
};
export const lockFile = (id: string) => {
const html = `<div class="b3-dialog__scrim"></div>
<div class="b3-dialog__container">
<div class="b3-dialog__header" onselectstart="return false;">🔒 ${window.siyuan.languages.lockFile0} <small>v${Constants.SIYUAN_VERSION}</small></div>
<div class="b3-dialog__content">
<p>${window.siyuan.languages.lockFile1}</p>
<p>${window.siyuan.languages.lockFile2}</p>
</div>
<div class="b3-dialog__action">
<button class="b3-button b3-button--cancel">${window.siyuan.languages.closeTab}</button>
<div class="fn__space"></div>
<button class="b3-button b3-button--text">${window.siyuan.languages.retry}</button>
</div>
</div>`;
let logElement = document.getElementById("errorLog");
if (logElement) {
logElement.innerHTML = html;
} else {
document.body.insertAdjacentHTML("beforeend", `<div id="errorLog" class="b3-dialog b3-dialog--open">${html}</div>`);
logElement = document.getElementById("errorLog");
}
logElement.querySelector(".b3-button--cancel").addEventListener("click", () => {
/// #if !MOBILE
getAllModels().editor.find((item) => {
if (item.editor.protyle.block.rootID === id) {
item.parent.parent.removeTab(item.parent.id, false, false);
return true;
}
});
logElement.remove();
/// #endif
});
logElement.querySelector(".b3-button--text").addEventListener("click", () => {
fetchPost("/api/filetree/lockFile", {id}, (response) => {
if (response.code === 0) {
window.location.reload();
}
});
});
};
export const kernelError = () => {
let iosReStart = "";
if (window.siyuan.config.system.container === "ios" && window.webkit?.messageHandlers) {
@ -162,10 +120,6 @@ export const exitSiYuan = () => {
};
export const transactionError = (data: { code: number, data: string }) => {
if (data.code === 1) {
lockFile(data.data);
return;
}
if (document.getElementById("transactionError")) {
return;
}

View file

@ -19,7 +19,7 @@ import {pushBack} from "../util/backForward";
import {Asset} from "../asset";
import {Layout} from "../layout";
import {hasClosestBlock, hasClosestByAttribute, hasClosestByClassName,} from "../protyle/util/hasClosest";
import {lockFile, setTitle} from "../dialog/processSystem";
import {setTitle} from "../dialog/processSystem";
import {zoomOut} from "../menus/protyle";
import {countBlockWord, countSelectWord} from "../layout/status";
import {showMessage} from "../dialog/message";
@ -34,11 +34,6 @@ export const openFileById = (options: {
removeCurrentTab?: boolean
}) => {
fetchPost("/api/block/getBlockInfo", {id: options.id}, (data) => {
if (data.code === 2) {
// 文件被锁定
lockFile(data.data);
return;
}
if (data.code === 3) {
showMessage(data.msg);
return;

View file

@ -7,7 +7,6 @@ import {disabledProtyle, onGet} from "../protyle/util/onGet";
import {addLoading} from "../protyle/ui/initUI";
import {focusBlock} from "../protyle/util/selection";
import {scrollCenter} from "../util/highlightById";
import {lockFile} from "../dialog/processSystem";
import {hasClosestByAttribute} from "../protyle/util/hasClosest";
import {setEditMode} from "../protyle/util/setEditMode";
import {hideElements} from "../protyle/ui/hideElements";
@ -40,11 +39,6 @@ export const openMobileFileById = (id: string, action = [Constants.CB_GET_HL]) =
}
fetchPost("/api/block/getBlockInfo", {id}, (data) => {
if (data.code === 2) {
// 文件被锁定
lockFile(data.data);
return;
}
if (data.code === 3) {
showMessage(data.msg);
return;

View file

@ -11,7 +11,6 @@ import {confirmDialog} from "../../dialog/confirmDialog";
import {getThemeMode, setInlineStyle} from "../../util/assets";
import {fetchPost} from "../../util/fetch";
import {Dialog} from "../../dialog";
import {lockFile} from "../../dialog/processSystem";
import {pathPosix} from "../../util/pathName";
import {replaceLocalPath} from "../../editor/rename";
import {setStorageVal} from "../util/compatibility";
@ -468,11 +467,6 @@ const getExportPath = (option: { type: string, id: string }, removeAssets?: bool
fetchPost("/api/block/getBlockInfo", {
id: option.id
}, (response) => {
if (response.code === 2) {
// 文件被锁定
lockFile(response.data);
return;
}
if (response.code === 3) {
showMessage(response.msg);
return;

View file

@ -1,4 +1,4 @@
import {lockFile, setTitle} from "../../dialog/processSystem";
import {setTitle} from "../../dialog/processSystem";
import {Constants} from "../../constants";
import {hideElements} from "../ui/hideElements";
import {genEmptyElement} from "../../block/util";
@ -36,12 +36,6 @@ export const onGet = (data: IWebSocketData, protyle: IProtyle, action: string[]
}
protyle.notebookId = data.data.box;
protyle.path = data.data.path;
if (data.code === 2) {
// 文件被锁定
protyle.block.rootID = data.data;
lockFile(data.data);
return;
}
if (data.data.eof) {
if (action.includes(Constants.CB_GET_BEFORE)) {

View file

@ -6,7 +6,6 @@ import {blockRender} from "../markdown/blockRender";
import {processRender} from "../util/processCode";
import {highlightRender} from "../markdown/highlightRender";
import {hasClosestBlock, hasClosestByAttribute} from "../util/hasClosest";
import {lockFile} from "../../dialog/processSystem";
import {setFold} from "../../menus/protyle";
import {onGet} from "../util/onGet";
/// #if !MOBILE
@ -69,10 +68,7 @@ const promiseTransaction = () => {
} else {
promiseTransaction();
}
if (response.code === 1) {
lockFile(protyle.block.rootID);
return;
}
countBlockWord([], protyle.block.rootID, true);
/// #if MOBILE
if ((0 !== window.siyuan.config.sync.provider || (0 === window.siyuan.config.sync.provider && !needSubscribe(""))) &&

View file

@ -10,7 +10,6 @@ import {Tab} from "../layout/Tab";
import {Editor} from "../editor";
import {onGet} from "../protyle/util/onGet";
import {scrollCenter} from "./highlightById";
import {lockFile} from "../dialog/processSystem";
import {zoomOut} from "../menus/protyle";
import {showMessage} from "../dialog/message";
import {saveScroll} from "../protyle/scroll/saveScroll";
@ -39,11 +38,6 @@ const focusStack = async (stack: IBackStack) => {
}
if (wnd) {
const info = await fetchSyncPost("/api/block/getBlockInfo", {id: stack.id});
if (info.code === 2) {
// 文件被锁定
lockFile(info.data);
return false;
}
if (info.code === 3) {
showMessage(info.msg);
return;

View file

@ -6,7 +6,6 @@ import {getCurrentWindow} from "@electron/remote";
import {Constants} from "../constants";
import {Tab} from "../layout/Tab";
import {fetchPost} from "../util/fetch";
import {lockFile} from "../dialog/processSystem";
import {showMessage} from "../dialog/message";
export const openNewWindow = (tab: Tab) => {
@ -23,11 +22,6 @@ export const openNewWindow = (tab: Tab) => {
export const openNewWindowById = (id: string) => {
fetchPost("api/block/getBlockInfo", {id}, (response) => {
if (response.code === 2) {
// 文件被锁定
lockFile(response.data);
return false;
}
if (response.code === 3) {
showMessage(response.msg);
return;

View file

@ -194,12 +194,6 @@ func checkBlockExist(c *gin.Context) {
id := arg["id"].(string)
b, err := model.GetBlock(id, nil)
// TODO 文件被锁的情况已经在 filelock 中做了退出进程处理,不会走到应用层,所以 code 为 2 的情况应该移除
//if errors.Is(err, filelock.ErrUnableAccessFile) {
// ret.Code = 2
// ret.Data = id
// return
//}
if errors.Is(err, model.ErrIndexing) {
ret.Code = 0
ret.Data = false
@ -405,11 +399,6 @@ func getBlockInfo(c *gin.Context) {
id := arg["id"].(string)
tree, err := model.LoadTreeByID(id)
//if errors.Is(err, filelock.ErrUnableAccessFile) {
// ret.Code = 2
// ret.Data = id
// return
//}
if errors.Is(err, model.ErrIndexing) {
ret.Code = 3
ret.Msg = model.Conf.Language(56)
@ -438,11 +427,6 @@ func getBlockInfo(c *gin.Context) {
}
root, err := model.GetBlock(block.RootID, tree)
//if errors.Is(err, filelock.ErrUnableAccessFile) {
// ret.Code = 2
// ret.Data = id
// return
//}
if errors.Is(err, model.ErrIndexing) {
ret.Code = 3
ret.Data = model.Conf.Language(56)

View file

@ -501,24 +501,6 @@ func createDocWithMd(c *gin.Context) {
pushCreate(box, p, id, arg)
}
func lockFile(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
id := arg["id"].(string)
locked := model.TryAccessFileByBlockID(id)
if !locked {
ret.Code = -1
ret.Msg = fmt.Sprintf(model.Conf.Language(75))
ret.Data = map[string]interface{}{"closeTimeout": 5000}
}
}
func getDocCreateSavePath(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
@ -689,11 +671,6 @@ func getDoc(c *gin.Context) {
}
blockCount, content, parentID, parent2ID, rootID, typ, eof, scroll, boxID, docPath, isBacklinkExpand, err := model.GetDoc(startID, endID, id, index, keyword, mode, size, isBacklink)
//if errors.Is(err, filelock.ErrUnableAccessFile) {
// ret.Code = 2
// ret.Data = id
// return
//}
if model.ErrBlockNotFound == err {
ret.Code = 3
return

View file

@ -89,7 +89,6 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/filetree/getDocCreateSavePath", model.CheckAuth, getDocCreateSavePath)
ginServer.Handle("POST", "/api/filetree/getRefCreateSavePath", model.CheckAuth, getRefCreateSavePath)
ginServer.Handle("POST", "/api/filetree/changeSort", model.CheckAuth, model.CheckReadonly, changeSort)
ginServer.Handle("POST", "/api/filetree/lockFile", model.CheckAuth, lockFile)
ginServer.Handle("POST", "/api/filetree/createDocWithMd", model.CheckAuth, model.CheckReadonly, createDocWithMd)
ginServer.Handle("POST", "/api/filetree/createDailyNote", model.CheckAuth, model.CheckReadonly, createDailyNote)
ginServer.Handle("POST", "/api/filetree/createDoc", model.CheckAuth, model.CheckReadonly, createDoc)
@ -263,6 +262,7 @@ func ServeAPI(ginServer *gin.Engine) {
ginServer.Handle("POST", "/api/setting/getCustomCSS", model.CheckAuth, getCustomCSS)
ginServer.Handle("POST", "/api/setting/setCustomCSS", model.CheckAuth, model.CheckReadonly, setCustomCSS)
ginServer.Handle("POST", "/api/setting/setEmoji", model.CheckAuth, model.CheckReadonly, setEmoji)
ginServer.Handle("POST", "/api/setting/setFlashcard", model.CheckAuth, model.CheckReadonly, setFlashcard)
ginServer.Handle("POST", "/api/graph/resetGraph", model.CheckAuth, model.CheckReadonly, resetGraph)
ginServer.Handle("POST", "/api/graph/resetLocalGraph", model.CheckAuth, model.CheckReadonly, resetLocalGraph)

View file

@ -29,6 +29,43 @@ import (
"github.com/siyuan-note/siyuan/kernel/util"
)
func setFlashcard(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)
arg, ok := util.JsonArg(c, ret)
if !ok {
return
}
param, err := gulu.JSON.MarshalJSON(arg)
if nil != err {
ret.Code = -1
ret.Msg = err.Error()
return
}
flashcard := &conf.Flashcard{}
if err = gulu.JSON.UnmarshalJSON(param, flashcard); nil != err {
ret.Code = -1
ret.Msg = err.Error()
return
}
if 1 > flashcard.DailyNewCardLimit {
flashcard.DailyNewCardLimit = 1
}
if 1 > flashcard.DailyReviewCardLimit {
flashcard.DailyReviewCardLimit = 1
}
model.Conf.Flashcard = flashcard
model.Conf.Save()
ret.Data = flashcard
}
func setAccount(c *gin.Context) {
ret := gulu.Ret.NewResult()
defer c.JSON(http.StatusOK, ret)

View file

@ -37,12 +37,13 @@ require (
github.com/mitchellh/go-ps v1.0.0
github.com/mssola/user_agent v0.6.0
github.com/olahol/melody v1.1.3
github.com/open-spaced-repetition/go-fsrs v0.1.0
github.com/panjf2000/ants/v2 v2.7.1
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/radovskyb/watcher v1.0.7
github.com/sashabaranov/go-gpt3 v1.4.0
github.com/shirou/gopsutil/v3 v3.23.2
github.com/siyuan-note/dejavu v0.0.0-20230315034343-e9513a7e1999
github.com/siyuan-note/dejavu v0.0.0-20230319084158-c8c1eaadf7bd
github.com/siyuan-note/encryption v0.0.0-20220713091850-5ecd92177b75
github.com/siyuan-note/eventbus v0.0.0-20230216103454-41885eac6c2b
github.com/siyuan-note/filelock v0.0.0-20230319015503-9ac4a0ee675b
@ -66,7 +67,7 @@ require (
github.com/alecthomas/chroma v0.10.0 // indirect
github.com/andybalholm/cascadia v1.3.1 // indirect
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef // indirect
github.com/aws/aws-sdk-go v1.44.221 // indirect
github.com/aws/aws-sdk-go v1.44.224 // indirect
github.com/bytedance/sonic v1.8.5 // indirect
github.com/cespare/xxhash/v2 v2.2.0 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
@ -107,14 +108,13 @@ require (
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/onsi/ginkgo/v2 v2.9.1 // indirect
github.com/open-spaced-repetition/go-fsrs v0.1.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/qiniu/go-sdk/v7 v7.14.0 // indirect
github.com/quic-go/qpack v0.4.0 // indirect
github.com/quic-go/qtls-go1-19 v0.2.1 // indirect
github.com/quic-go/qtls-go1-20 v0.1.1 // indirect
github.com/quic-go/qtls-go1-19 v0.3.0 // indirect
github.com/quic-go/qtls-go1-20 v0.2.0 // indirect
github.com/quic-go/quic-go v0.33.0 // indirect
github.com/restic/chunker v0.4.0 // indirect
github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 // indirect
@ -128,7 +128,7 @@ require (
github.com/yusufpapurcu/wmi v1.2.2 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/crypto v0.7.0 // indirect
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec // indirect
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sync v0.1.0 // indirect
golang.org/x/sys v0.6.0 // indirect

View file

@ -37,8 +37,8 @@ github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de h1:FxWPpzIjnTlhP
github.com/araddon/dateparse v0.0.0-20210429162001-6b43995a97de/go.mod h1:DCaWoUhZrYW9p1lxo/cm8EmUOOzAPSEZNGF2DK1dJgw=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef h1:2JGTg6JapxP9/R33ZaagQtAM4EkkSYnIAlOG5EI8gkM=
github.com/asaskevich/EventBus v0.0.0-20200907212545-49d423059eef/go.mod h1:JS7hed4L1fj0hXcyEejnW57/7LCetXggd+vwrRnYeII=
github.com/aws/aws-sdk-go v1.44.221 h1:yndn4uvLolKXPoXIwKHhO5XtwlTnJfXLBKXs84C5+hQ=
github.com/aws/aws-sdk-go v1.44.221/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/aws/aws-sdk-go v1.44.224 h1:09CiaaF35nRmxrzWZ2uRq5v6Ghg/d2RiPjZnSgtt+RQ=
github.com/aws/aws-sdk-go v1.44.224/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.8.5 h1:kjX0/vo5acEQ/sinD/18SkA/lDDUk23F0RcaHvI7omc=
github.com/bytedance/sonic v1.8.5/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
@ -250,10 +250,10 @@ github.com/qiniu/go-sdk/v7 v7.14.0/go.mod h1:btsaOc8CA3hdVloULfFdDgDc+g4f3TDZEFs
github.com/qiniu/x v1.10.5/go.mod h1:03Ni9tj+N2h2aKnAz+6N0Xfl8FwMEDRC2PAlxekASDs=
github.com/quic-go/qpack v0.4.0 h1:Cr9BXA1sQS2SmDUWjSofMPNKmvF6IiIfDRmgU0w1ZCo=
github.com/quic-go/qpack v0.4.0/go.mod h1:UZVnYIfi5GRk+zI9UMaCPsmZ2xKJP7XBUvVyT1Knj9A=
github.com/quic-go/qtls-go1-19 v0.2.1 h1:aJcKNMkH5ASEJB9FXNeZCyTEIHU1J7MmHyz1Q1TSG1A=
github.com/quic-go/qtls-go1-19 v0.2.1/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.1.1 h1:KbChDlg82d3IHqaj2bn6GfKRj84Per2VGf5XV3wSwQk=
github.com/quic-go/qtls-go1-20 v0.1.1/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/qtls-go1-19 v0.3.0 h1:aUBoQdpHzUWtPw5tQZbsD2GnrWCNu7/RIX1PtqGeLYY=
github.com/quic-go/qtls-go1-19 v0.3.0/go.mod h1:ySOI96ew8lnoKPtSqx2BlI5wCpUVPT05RMAlajtnyOI=
github.com/quic-go/qtls-go1-20 v0.2.0 h1:jUHn+obJ6WI5JudqBO0Iy1ra5Vh5vsitQ1gXQvkmN+E=
github.com/quic-go/qtls-go1-20 v0.2.0/go.mod h1:JKtK6mjbAVcUTN/9jZpvLbGxvdWIKS8uT7EiStoU1SM=
github.com/quic-go/quic-go v0.33.0 h1:ItNoTDN/Fm/zBlq769lLJc8ECe9gYaW40veHCCco7y0=
github.com/quic-go/quic-go v0.33.0/go.mod h1:YMuhaAV9/jIu0XclDXwZPAsP/2Kgr5yMYhe9oxhhOFA=
github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE=
@ -277,8 +277,8 @@ github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5g
github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
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/siyuan-note/dejavu v0.0.0-20230315034343-e9513a7e1999 h1:t4FSwNVaa2CJbAIJNyF5egCdgqAeBDbP0WmGXcPBbGs=
github.com/siyuan-note/dejavu v0.0.0-20230315034343-e9513a7e1999/go.mod h1:KUsHkTYpibU30rUArZOakCCHF1SGHQlxPWUu2LqW72s=
github.com/siyuan-note/dejavu v0.0.0-20230319084158-c8c1eaadf7bd h1:h46K2Da4gmnDtXniCTX9p0NEP5toLd4qeTJ4teRiyns=
github.com/siyuan-note/dejavu v0.0.0-20230319084158-c8c1eaadf7bd/go.mod h1:8fvMTYkfHRBn13YyZxbRfk2GCxDFszYlJfyyYFkvvNU=
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-20230216103454-41885eac6c2b h1:828lTUW2C0uNiolODqoACu7J8sDUzswD4Xo04mUombg=
@ -351,8 +351,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec h1:pAv+d8BM2JNnNctsLJ6nnZ6NqXT8N4+eauvZSb3P0I0=
golang.org/x/exp v0.0.0-20230314191032-db074128a8ec/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0 h1:pVgRXcIictcr+lBQIFeiwuwtDIs4eL21OuM9nyAADmo=
golang.org/x/exp v0.0.0-20230315142452-642cacee5cc0/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM=

View file

@ -527,19 +527,6 @@ func (box *Box) UpdateHistoryGenerated() {
boxLatestHistoryTime[box.ID] = time.Now()
}
func TryAccessFileByBlockID(id string) (ok bool) {
bt := treenode.GetBlockTree(id)
if nil == bt {
return
}
p := filepath.Join(util.DataDir, bt.BoxID, bt.Path)
if !gulu.File.IsExist(p) {
return false
}
return true
}
func getBoxesByPaths(paths []string) (ret map[string]*Box) {
ret = map[string]*Box{}
for _, p := range paths {

View file

@ -29,6 +29,7 @@ import (
"github.com/88250/gulu"
"github.com/88250/lute/ast"
"github.com/88250/lute/parse"
"github.com/open-spaced-repetition/go-fsrs"
"github.com/siyuan-note/logging"
"github.com/siyuan-note/riff"
"github.com/siyuan-note/siyuan/kernel/cache"
@ -634,6 +635,10 @@ func removeFlashcardsByBlockIDs(blockIDs []string, deck *riff.Deck) {
}
cards := deck.GetCardsByBlockIDs(blockIDs)
if 1 > len(cards) {
return
}
for _, card := range cards {
deck.RemoveCard(card.ID())
}
@ -900,11 +905,20 @@ func getDeckDueCards(deck *riff.Deck) (ret []riff.Card) {
ret = []riff.Card{}
dues := deck.Dues()
newCount := 0
reviewCount := 0
for _, c := range dues {
if nil != skipCardCache[c.ID()] {
continue
}
fsrsCard := c.Impl().(*fsrs.Card)
if fsrs.New == fsrsCard.State {
newCount++
} else {
reviewCount++
}
ret = append(ret, c)
}
return

View file

@ -130,105 +130,116 @@ func ReportFileSysFatalError(err error) {
os.Exit(logging.ExitCodeFileSysErr)
}
var checkFileSysStatusLock = sync.Mutex{}
func CheckFileSysStatus() {
if ContainerStd != Container {
return
}
const fileSysStatusCheckFile = ".siyuan/filesys_status_check"
for {
<-thirdPartySyncCheckTicker.C
checkFileSysStatus()
}
}
if IsCloudDrivePath(WorkspaceDir) {
ReportFileSysFatalError(fmt.Errorf("workspace dir [%s] is in third party sync dir", WorkspaceDir))
return
}
func checkFileSysStatus() {
if IsMutexLocked(&checkFileSysStatusLock) {
logging.LogWarnf("check file system status is locked, skip")
return
}
dir := filepath.Join(DataDir, fileSysStatusCheckFile)
if err := os.RemoveAll(dir); nil != err {
checkFileSysStatusLock.Lock()
defer checkFileSysStatusLock.Unlock()
const fileSysStatusCheckFile = ".siyuan/filesys_status_check"
if IsCloudDrivePath(WorkspaceDir) {
ReportFileSysFatalError(fmt.Errorf("workspace dir [%s] is in third party sync dir", WorkspaceDir))
return
}
dir := filepath.Join(DataDir, fileSysStatusCheckFile)
if err := os.RemoveAll(dir); nil != err {
ReportFileSysFatalError(err)
return
}
if err := os.MkdirAll(dir, 0755); nil != err {
ReportFileSysFatalError(err)
return
}
for i := 0; i < 7; i++ {
tmp := filepath.Join(dir, "check_consistency")
data := make([]byte, 1024*4)
_, err := rand.Read(data)
if nil != err {
ReportFileSysFatalError(err)
return
}
if err := os.MkdirAll(dir, 0755); nil != err {
if err = os.WriteFile(tmp, data, 0644); nil != err {
ReportFileSysFatalError(err)
return
}
for i := 0; i < 7; i++ {
tmp := filepath.Join(dir, "check_consistency")
data := make([]byte, 1024*4)
_, err := rand.Read(data)
time.Sleep(5 * time.Second)
for j := 0; j < 32; j++ {
renamed := tmp + "_renamed"
if err = os.Rename(tmp, renamed); nil != err {
ReportFileSysFatalError(err)
break
}
time.Sleep(time.Second)
f, err := os.Open(renamed)
if nil != err {
ReportFileSysFatalError(err)
return
}
if err = os.WriteFile(tmp, data, 0644); nil != err {
if err = f.Close(); nil != err {
ReportFileSysFatalError(err)
return
}
time.Sleep(5 * time.Second)
for j := 0; j < 32; j++ {
renamed := tmp + "_renamed"
if err = os.Rename(tmp, renamed); nil != err {
ReportFileSysFatalError(err)
break
}
time.Sleep(time.Second)
f, err := os.Open(renamed)
if nil != err {
ReportFileSysFatalError(err)
return
}
if err = f.Close(); nil != err {
ReportFileSysFatalError(err)
return
}
if err = os.Rename(renamed, tmp); nil != err {
ReportFileSysFatalError(err)
return
}
entries, err := os.ReadDir(dir)
if nil != err {
ReportFileSysFatalError(err)
return
}
checkFilenames := bytes.Buffer{}
for _, entry := range entries {
if !entry.IsDir() && strings.Contains(entry.Name(), "check_") {
checkFilenames.WriteString(entry.Name())
checkFilenames.WriteString("\n")
}
}
lines := strings.Split(strings.TrimSpace(checkFilenames.String()), "\n")
if 1 < len(lines) {
buf := bytes.Buffer{}
for _, line := range lines {
buf.WriteString(" ")
buf.WriteString(line)
buf.WriteString("\n")
}
output := buf.String()
ReportFileSysFatalError(fmt.Errorf("dir [%s] has more than 1 file:\n%s", dir, output))
return
}
}
if err = os.RemoveAll(tmp); nil != err {
if err = os.Rename(renamed, tmp); nil != err {
ReportFileSysFatalError(err)
return
}
entries, err := os.ReadDir(dir)
if nil != err {
ReportFileSysFatalError(err)
return
}
checkFilenames := bytes.Buffer{}
for _, entry := range entries {
if !entry.IsDir() && strings.Contains(entry.Name(), "check_") {
checkFilenames.WriteString(entry.Name())
checkFilenames.WriteString("\n")
}
}
lines := strings.Split(strings.TrimSpace(checkFilenames.String()), "\n")
if 1 < len(lines) {
buf := bytes.Buffer{}
for _, line := range lines {
buf.WriteString(" ")
buf.WriteString(line)
buf.WriteString("\n")
}
output := buf.String()
ReportFileSysFatalError(fmt.Errorf("dir [%s] has more than 1 file:\n%s", dir, output))
return
}
}
if err = os.RemoveAll(tmp); nil != err {
ReportFileSysFatalError(err)
return
}
}
}

View file

@ -397,7 +397,7 @@ func initPandoc() {
}
pandocZip := filepath.Join(WorkingDir, "pandoc.zip")
if "dev" == Mode {
if "dev" == Mode || !gulu.File.IsExist(pandocZip) {
if gulu.OS.IsWindows() {
pandocZip = filepath.Join(WorkingDir, "pandoc/pandoc-windows-amd64.zip")
} else if gulu.OS.IsDarwin() {