Vanessa 2023-06-04 00:10:33 +08:00
parent 2663d0a4f4
commit 158b534651
3 changed files with 75 additions and 66 deletions

View file

@ -11,6 +11,7 @@ import {isMobile} from "../util/functions";
import {App} from "../index"; import {App} from "../index";
let historyEditor: Protyle; let historyEditor: Protyle;
let isLoading = false;
const renderDoc = (element: HTMLElement, currentPage: number, id: string) => { const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
const previousElement = element.querySelector('[data-type="docprevious"]'); const previousElement = element.querySelector('[data-type="docprevious"]');
@ -22,12 +23,9 @@ const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
previousElement.setAttribute("disabled", "disabled"); previousElement.setAttribute("disabled", "disabled");
} }
const opElement = element.querySelector('.b3-select[data-type="opselect"]') as HTMLSelectElement; const opElement = element.querySelector('.b3-select[data-type="opselect"]') as HTMLSelectElement;
const docElement = element.querySelector('.history__text[data-type="docPanel"]'); const listElement = element.querySelector('.b3-list--background')
const assetElement = element.querySelector('.history__text[data-type="assetPanel"]'); element.querySelector('.history__text[data-type="docPanel"]').classList.add("fn__none");
const mdElement = element.querySelector('.history__text[data-type="mdPanel"]') as HTMLTextAreaElement; element.querySelector('.history__text[data-type="mdPanel"]').classList.add("fn__none");
docElement.classList.add("fn__none");
mdElement.classList.add("fn__none");
assetElement.classList.remove("fn__none");
fetchPost("/api/history/searchHistory", { fetchPost("/api/history/searchHistory", {
query: id, query: id,
page: currentPage, page: currentPage,
@ -41,30 +39,32 @@ const renderDoc = (element: HTMLElement, currentPage: number, id: string) => {
} }
nextElement.nextElementSibling.nextElementSibling.textContent = `${currentPage}/${response.data.pageCount || 1}`; nextElement.nextElementSibling.nextElementSibling.textContent = `${currentPage}/${response.data.pageCount || 1}`;
if (response.data.histories.length === 0) { if (response.data.histories.length === 0) {
element.lastElementChild.lastElementChild.previousElementSibling.classList.add("fn__none"); listElement.innerHTML = `<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>`;
element.lastElementChild.lastElementChild.classList.add("fn__none");
element.lastElementChild.firstElementChild.innerHTML = `<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>`;
return; return;
} }
let logsHTML = ""; let logsHTML = "";
response.data.histories.forEach((item: string) => { response.data.histories.forEach((item: string) => {
logsHTML += `<li class="b3-list-item" data-type="toggle" data-created="${item}"> logsHTML += `<li class="b3-list-item" data-created="${item}">
<span class="b3-list-item__toggle b3-list-item__toggle--hl"><svg class="b3-list-item__arrow"><use xlink:href="#iconRight"></use></svg></span> <span class="b3-list-item__text">${dayjs(parseInt(item) * 1000).format("YYYY-MM-DD HH:mm:ss")}</span>
<span style="padding-left: 4px" class="b3-list-item__text">${dayjs(parseInt(item) * 1000).format("YYYY-MM-DD HH:mm:ss")}</span> <span class="fn__space"></span>
<span class="b3-list-item__action b3-tooltips b3-tooltips__w" data-type="rollback" aria-label="${window.siyuan.languages.rollback}">
<svg><use xlink:href="#iconUndo"></use></svg>
</span>
</li>`; </li>`;
}); });
element.lastElementChild.firstElementChild.innerHTML = logsHTML; listElement.innerHTML = logsHTML;
}); });
}; };
export const openDocHistory = (app: App, id: string) => { export const openDocHistory = (options: {
app: App,
id: string,
notebookId: string,
pathString: string
}) => {
const contentHTML = `<div class="fn__flex-column" style="height: 100%;"> const contentHTML = `<div class="fn__flex-column" style="height: 100%;">
<div class="block__icons"> <div class="block__icons">
<span data-type="docprevious" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href='#iconLeft'></use></svg></span> ${isMobile() ? "" : options.pathString}
<span class="fn__space"></span>
<span data-type="docnext" class="block__icon block__icon--show b3-tooltips b3-tooltips__e" disabled="disabled" aria-label="${window.siyuan.languages.nextLabel}"><svg><use xlink:href='#iconRight'></use></svg></span>
<span class="fn__space"></span>
<span>1/1</span>
<span class="fn__space"></span> <span class="fn__space"></span>
<div class="fn__flex-1"></div> <div class="fn__flex-1"></div>
<select data-type="opselect" class="b3-select"> <select data-type="opselect" class="b3-select">
@ -76,36 +76,39 @@ export const openDocHistory = (app: App, id: string) => {
<option value="sync">sync</option> <option value="sync">sync</option>
<option value="replace">replace</option> <option value="replace">replace</option>
</select> </select>
<span class="fn__space"></span>
<span data-type="docprevious" class="block__icon block__icon--show b3-tooltips b3-tooltips__s" disabled="disabled" aria-label="${window.siyuan.languages.previousLabel}"><svg><use xlink:href="#iconLeft"></use></svg></span>
<span class="fn__space"></span>
<span data-type="docnext" class="block__icon block__icon--show b3-tooltips b3-tooltips__s" disabled="disabled" aria-label="${window.siyuan.languages.nextLabel}"><svg><use xlink:href="#iconRight"></use></svg></span>
<span class="fn__space"></span>
<span>1/1</span>
${isMobile() ? '<span class="fn__space"></span><span data-type="close" class="block__icon block__icon--show"><svg><use xlink:href="#iconClose"></use></svg></span>' : ""}
</div> </div>
<div class="fn__flex fn__flex-1"> <div class="fn__flex fn__flex-1 history__panel">
<ul class="b3-list b3-list--background" style="overflow:auto;"> <ul class="b3-list b3-list--background" style="overflow:auto;">
<li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li> <li class="b3-list--empty">${window.siyuan.languages.emptyContent}</li>
</ul> </ul>
<div class="fn__flex-1 history__text fn__none" data-type="assetPanel"></div> <textarea class="fn__flex-1 history__text fn__none" readonly data-type="mdPanel"></textarea>
<textarea class="fn__flex-1 history__text fn__none" data-type="mdPanel"></textarea>
<div class="fn__flex-1 history__text fn__none" style="padding: 0" data-type="docPanel"></div> <div class="fn__flex-1 history__text fn__none" style="padding: 0" data-type="docPanel"></div>
</div> </div>
</div>`; </div>`;
const dialog = new Dialog({ const dialog = new Dialog({
content: contentHTML, content: contentHTML,
width: isMobile() ? "92vw" : "768px", width: isMobile() ? "100vw" : "1024px",
height: isMobile() ? "80vh" : "70vh", height: isMobile() ? "100vh" : "80vh",
destroyCallback() { destroyCallback() {
historyEditor = undefined; historyEditor = undefined;
} }
}); });
bindEvent(app, dialog.element, id);
};
const bindEvent = (app: App, element: HTMLElement, id: string) => { const opElement = dialog.element.querySelector(".b3-select") as HTMLSelectElement;
element.querySelector(".b3-select").addEventListener("change", () => { opElement.addEventListener("change", () => {
renderDoc(element, 1, id); renderDoc(dialog.element, 1, options.id);
}); });
const docElement = element.querySelector('.history__text[data-type="docPanel"]') as HTMLElement; const docElement = dialog.element.querySelector('.history__text[data-type="docPanel"]') as HTMLElement;
const assetElement = element.querySelector('.history__text[data-type="assetPanel"]'); const mdElement = dialog.element.querySelector('.history__text[data-type="mdPanel"]') as HTMLTextAreaElement;
const mdElement = element.querySelector('.history__text[data-type="mdPanel"]') as HTMLTextAreaElement; renderDoc(dialog.element, 1, options.id);
renderDoc(element, 1, id); historyEditor = new Protyle(options.app, docElement, {
historyEditor = new Protyle(app, docElement, {
blockId: "", blockId: "",
action: [Constants.CB_GET_HISTORY], action: [Constants.CB_GET_HISTORY],
render: { render: {
@ -118,35 +121,29 @@ const bindEvent = (app: App, element: HTMLElement, id: string) => {
typewriterMode: false, typewriterMode: false,
}); });
disabledProtyle(historyEditor.protyle); disabledProtyle(historyEditor.protyle);
element.addEventListener("click", (event) => { dialog.element.addEventListener("click", (event) => {
let target = event.target as HTMLElement; let target = event.target as HTMLElement;
while (target && !target.isEqualNode(element)) { while (target && !target.isEqualNode(dialog.element)) {
const type = target.getAttribute("data-type"); const type = target.getAttribute("data-type");
if (target.classList.contains("b3-list-item__action") && type === "rollback" && !window.siyuan.config.readonly) { if (type === "close") {
dialog.destroy()
} else if (type === "rollback" && !isLoading) {
getHistoryPath(target.parentElement, opElement.value, options.id, (dataPath) => {
isLoading = false;
confirmDialog("⚠️ " + window.siyuan.languages.rollback, `${window.siyuan.languages.rollbackConfirm.replace("${date}", target.parentElement.textContent.trim())}`, () => { confirmDialog("⚠️ " + window.siyuan.languages.rollback, `${window.siyuan.languages.rollbackConfirm.replace("${date}", target.parentElement.textContent.trim())}`, () => {
const dataType = target.parentElement.getAttribute("data-type");
if (dataType === "assets") {
fetchPost("/api/history/rollbackAssetsHistory", {
historyPath: target.parentElement.getAttribute("data-path")
});
} else if (dataType === "doc") {
fetchPost("/api/history/rollbackDocHistory", { fetchPost("/api/history/rollbackDocHistory", {
// notebook: (firstPanelElement.querySelector('.b3-select[data-type="notebookselect"]') as HTMLSelectElement).value, notebook: options.notebookId,
historyPath: target.parentElement.getAttribute("data-path") historyPath: dataPath
});
}); });
}
}); });
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
break; break;
} else if (target.classList.contains("b3-list-item")) { } else if (target.classList.contains("b3-list-item") && !isLoading) {
const dataPath = target.getAttribute("data-path"); getHistoryPath(target, opElement.value, options.notebookId, (dataPath) => {
if (type === "assets") {
assetElement.innerHTML = renderAssetsPreview(dataPath);
} else if (type === "doc") {
fetchPost("/api/history/getDocHistoryContent", { fetchPost("/api/history/getDocHistoryContent", {
historyPath: dataPath, historyPath: dataPath,
// k: (firstPanelElement.querySelector(".b3-text-field") as HTMLInputElement).value
}, (response) => { }, (response) => {
if (response.data.isLargeDoc) { if (response.data.isLargeDoc) {
mdElement.value = response.data.content; mdElement.value = response.data.content;
@ -161,22 +158,17 @@ const bindEvent = (app: App, element: HTMLElement, id: string) => {
action: [Constants.CB_GET_HISTORY, Constants.CB_GET_HTML], action: [Constants.CB_GET_HISTORY, Constants.CB_GET_HTML],
}); });
} }
isLoading = false;
}); });
} target.parentElement.querySelector(".b3-list-item--focus")?.classList.remove("b3-list-item--focus");
let currentItem = hasClosestByClassName(target, "b3-list") as HTMLElement;
if (currentItem) {
currentItem = currentItem.querySelector(".b3-list-item--focus");
if (currentItem) {
currentItem.classList.remove("b3-list-item--focus");
}
}
target.classList.add("b3-list-item--focus"); target.classList.add("b3-list-item--focus");
});
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
break; break;
} else if ((type === "docprevious" || type === "docnext") && target.getAttribute("disabled") !== "disabled") { } else if ((type === "docprevious" || type === "docnext") && target.getAttribute("disabled") !== "disabled") {
const currentPage = parseInt(element.getAttribute("data-page")); const currentPage = parseInt(dialog.element.getAttribute("data-page"));
renderDoc(element, type === "docprevious" ? currentPage - 1 : currentPage + 1, id); renderDoc(dialog.element, type === "docprevious" ? currentPage - 1 : currentPage + 1, options.id);
event.stopPropagation(); event.stopPropagation();
event.preventDefault(); event.preventDefault();
break; break;
@ -185,3 +177,20 @@ const bindEvent = (app: App, element: HTMLElement, id: string) => {
} }
}); });
}; };
const getHistoryPath = (target: Element, op: string, id: string, cb: (path: string) => void) => {
isLoading = true;
const path = target.getAttribute("data-path")
if (path) {
cb(path);
}
fetchPost("/api/history/getHistoryItems", {
query: id,
op,
type: 3,
created: target.getAttribute("data-created")
}, (response) => {
cb(response.data.items[0].path)
});
}

View file

@ -546,7 +546,7 @@ export const initFileMenu = (app: App, notebookId: string, pathString: string, l
label: window.siyuan.languages.dataHistory, label: window.siyuan.languages.dataHistory,
icon: "iconHistory", icon: "iconHistory",
click() { click() {
openDocHistory(app, id); openDocHistory({app, id, notebookId, pathString: name});
} }
}).element); }).element);
} }

View file

@ -148,9 +148,9 @@ export const afterLoadPlugin = (plugin: Plugin) => {
document.querySelector("#" + (element.getAttribute("data-position") === "right" ? "barPlugins" : "drag")).before(element); document.querySelector("#" + (element.getAttribute("data-position") === "right" ? "barPlugins" : "drag")).before(element);
} }
}); });
resizeTopbar();
} }
/// #if !MOBILE /// #if !MOBILE
resizeTopbar();
mergePluginHotkey(plugin); mergePluginHotkey(plugin);
plugin.statusBarIcons.forEach(element => { plugin.statusBarIcons.forEach(element => {
const statusElement = document.getElementById("status"); const statusElement = document.getElementById("status");