Vanessa 2023-02-11 12:33:09 +08:00
parent eb597e719d
commit 165457429b
9 changed files with 200 additions and 86 deletions

View file

@ -11,6 +11,13 @@
}
}
&--float {
position: fixed;
z-index: 2;
min-height: auto;
transition: left .15s cubic-bezier(0, 0.88, 0.42, 0.74) 0ms, opacity .15s cubic-bezier(0, 0.88, 0.42, 0.74) 0ms;
}
&__tab--active {
.b3-list--background .b3-list-item--focus:not(.dragover):not(.dragover__top):not(.dragover__bottom) {
background-color: var(--b3-theme-primary-lightest);
@ -316,7 +323,8 @@
margin: 5px;
&:hover,
&--active {
&--active,
&--pin {
background-color: var(--b3-theme-background-light);
}

View file

@ -338,8 +338,14 @@ progressLoading: 400
}
}
#barDock .b3-menu__item:hover {
background-color: var(--b3-list-hover);
#barDock {
&:hover .b3-menu {
display: block !important;
}
.b3-menu__item:hover {
background-color: var(--b3-list-hover);
}
}
.fn__space:last-child {

View file

@ -100,7 +100,7 @@ const hidePopover = (event: MouseEvent & { target: HTMLElement, path: HTMLElemen
// 移动到弹窗的 loading 元素上,但经过 settimeout 后 loading 已经被移除了
// https://ld246.com/article/1673596577519/comment/1673767749885#comments
let targetElement = event.target;
if (!targetElement.parentElement && event.path[1]) {
if (!targetElement.parentElement && event.path && event.path[1]) {
targetElement = event.path[1];
}
const blockElement = hasClosestByClassName(targetElement, "block__popover", true);

View file

@ -315,62 +315,74 @@ export abstract class Constants {
}]
}]
},
top: [],
bottom: [],
left: [
[{
type: "file",
size: {width: 240, height: 0},
show: true,
icon: "iconFiles",
hotkeyLangId: "fileTree",
}, {
type: "outline",
size: {width: 240, height: 0},
show: false,
icon: "iconAlignCenter",
hotkeyLangId: "outline",
}, {
type: "inbox",
size: {width: 252, height: 0},
show: false,
icon: "iconInbox",
hotkeyLangId: "inbox",
}], [{
type: "bookmark",
size: {width: 240, height: 0},
show: false,
icon: "iconBookmark",
hotkeyLangId: "bookmark",
}, {
type: "tag",
size: {width: 240, height: 0},
show: false,
icon: "iconTags",
hotkeyLangId: "tag",
}]
],
right: [
[{
type: "graph",
size: {width: 360, height: 0},
show: false,
icon: "iconGraph",
hotkeyLangId: "graphView",
}, {
type: "globalGraph",
size: {width: 360, height: 0},
show: false,
icon: "iconGlobalGraph",
hotkeyLangId: "globalGraph",
}], [{
type: "backlink",
size: {width: 360, height: 0},
show: false,
icon: "iconLink",
hotkeyLangId: "backlinks",
}]
]
top: {
pin: true,
data: []
},
bottom: {
pin: true,
data: []
},
left: {
pin: true,
data: [
[{
type: "file",
size: {width: 240, height: 0},
show: true,
icon: "iconFiles",
hotkeyLangId: "fileTree",
}, {
type: "outline",
size: {width: 240, height: 0},
show: false,
icon: "iconAlignCenter",
hotkeyLangId: "outline",
}, {
type: "inbox",
size: {width: 252, height: 0},
show: false,
icon: "iconInbox",
hotkeyLangId: "inbox",
}], [{
type: "bookmark",
size: {width: 240, height: 0},
show: false,
icon: "iconBookmark",
hotkeyLangId: "bookmark",
}, {
type: "tag",
size: {width: 240, height: 0},
show: false,
icon: "iconTags",
hotkeyLangId: "tag",
}]
]
},
right: {
pin: true,
data: [
[{
type: "graph",
size: {width: 360, height: 0},
show: false,
icon: "iconGraph",
hotkeyLangId: "graphView",
}, {
type: "globalGraph",
size: {width: 360, height: 0},
show: false,
icon: "iconGlobalGraph",
hotkeyLangId: "globalGraph",
}], [{
type: "backlink",
size: {width: 360, height: 0},
show: false,
icon: "iconLink",
hotkeyLangId: "backlinks",
}]
]
}
};
// image

View file

@ -19,9 +19,10 @@ export class Dock {
public layout: Layout;
private position: TDockPosition;
public resizeElement: HTMLElement;
public pin = true;
public data: { [key: string]: Model | boolean };
constructor(options: { data: IDockTab[][], position: TDockPosition }) {
constructor(options: { data: { pin: boolean, data: IDockTab[][] }, position: TDockPosition }) {
switch (options.position) {
case "Left":
this.layout = window.siyuan.layout.layout.children[1].children[0] as Layout;
@ -44,16 +45,16 @@ export class Dock {
const dockClass = (options.position === "Bottom" || options.position === "Top") ? ' class="fn__flex"' : "";
this.element.innerHTML = `<div${dockClass}></div><div class="fn__flex-1"></div><div${dockClass}></div>`;
this.position = options.position;
this.pin = options.data.pin
this.data = {};
if (options.data.length === 0) {
if (options.data.data.length === 0) {
this.element.classList.add("fn__none");
} else {
this.genButton(options.data[0], 0);
if (options.data[1]) {
this.genButton(options.data[1], 1);
this.genButton(options.data.data[0], 0);
if (options.data.data[1]) {
this.genButton(options.data.data[1], 1);
}
}
const activeElements = this.element.querySelectorAll(".dock__item--active");
// 初始化文件树
@ -71,7 +72,6 @@ export class Dock {
this.toggleModel(item.getAttribute("data-type") as TDockType, true);
});
}
this.element.addEventListener("click", (event) => {
let target = event.target as HTMLElement;
while (target && !target.isEqualNode(this.element)) {
@ -80,16 +80,54 @@ export class Dock {
this.toggleModel(type, false, true);
event.preventDefault();
break;
} else if (target.classList.contains("dock__item")) {
this.pin = !target.classList.contains("dock__item--pin");
if (!this.pin) {
const layoutRect = this.layout.element.getBoundingClientRect();
this.layout.element.setAttribute("style", `left:${layoutRect.left}px; top: ${layoutRect.top}px; bottom: ${window.innerHeight - layoutRect.bottom}px; width: ${layoutRect.width}px;`);
}
target.classList.toggle("dock__item--pin");
this.layout.element.classList.toggle("layout--float");
this.resizeElement.classList.toggle("fn__none");
event.preventDefault();
break;
}
target = target.parentElement;
}
});
this.layout.element.addEventListener("mouseleave", (event) => {
if (this.pin) {
return
}
if (this.position === "Left" && event.clientX < 43) {
return;
}
this.hideDock()
})
if (window.siyuan.config.uiLayout.hideDock) {
this.element.classList.add("fn__none");
}
if (!this.pin) {
setTimeout(() => {
const layoutRect = this.layout.element.getBoundingClientRect();
this.layout.element.setAttribute("style", `width:${layoutRect.width}px;opacity:0px;left:-${layoutRect.width}px; top: ${layoutRect.top}px; bottom: ${window.innerHeight - layoutRect.bottom}px;`);
this.layout.element.classList.add("layout--float");
this.resizeElement.classList.add("fn__none");
}, 1000);
}
}
public hideDock() {
if (this.layout.element.style.opacity === "1") {
this.layout.element.style.left = -this.layout.element.clientWidth + "px";
this.layout.element.style.opacity = "0";
}
}
public toggleModel(type: TDockType, show = false, close = false) {
if (!type) {
return;
}
const target = this.element.querySelector(`[data-type="${type}"]`) as HTMLElement;
if (show && target.classList.contains("dock__item--active")) {
target.classList.remove("dock__item--active", "dock__item--activefocus");
@ -395,7 +433,9 @@ export class Dock {
}
private genButton(data: IDockTab[], index: number) {
let html = "";
let html = index ? "" : `<span class="dock__item ${this.pin ? "dock__item--pin " : ""}b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${window.siyuan.languages.pin}">
<svg><use xlink:href="#iconPin"></use></svg>
</span>`;
data.forEach(item => {
html += `<span data-height="${item.size.height}" data-width="${item.size.width}" data-type="${item.type}" data-index="${index}" data-hotkeylangid="${item.hotkeyLangId}" class="dock__item${item.show ? " dock__item--active" : ""} b3-tooltips b3-tooltips__${this.getClassDirect(index)}" aria-label="${window.siyuan.languages[item.hotkeyLangId] + " " + updateHotkeyTip(window.siyuan.config.keymap.general[item.hotkeyLangId].custom)}${window.siyuan.languages.dockTip}">
<svg><use xlink:href="#${item.icon}"></use></svg>

View file

@ -67,22 +67,22 @@ export const getAllTabs = () => {
export const getAllDocks = () => {
const docks: IDockTab[] = [];
window.siyuan.config.uiLayout.left.forEach((item: IDockTab[]) => {
window.siyuan.config.uiLayout.left.data.forEach((item: IDockTab[]) => {
item.forEach((dock: IDockTab) => {
docks.push(dock);
});
});
window.siyuan.config.uiLayout.right.forEach((item: IDockTab[]) => {
window.siyuan.config.uiLayout.right.data.forEach((item: IDockTab[]) => {
item.forEach((dock: IDockTab) => {
docks.push(dock);
});
});
window.siyuan.config.uiLayout.top.forEach((item: IDockTab[]) => {
window.siyuan.config.uiLayout.top.data.forEach((item: IDockTab[]) => {
item.forEach((dock: IDockTab) => {
docks.push(dock);
});
});
window.siyuan.config.uiLayout.bottom.forEach((item: IDockTab[]) => {
window.siyuan.config.uiLayout.bottom.data.forEach((item: IDockTab[]) => {
item.forEach((dock: IDockTab) => {
docks.push(dock);
});

View file

@ -38,15 +38,6 @@ export const initStatus = (isWindow = false) => {
<div id="statusHelp" class="toolbar__item b3-tooltips b3-tooltips__w" aria-label="${window.siyuan.languages.help}">
<svg><use xlink:href="#iconHelp"></use></svg>
</div>`;
if (!isWindow) {
const dockElement = document.getElementById("barDock");
dockElement.addEventListener("mousemove", () => {
dockElement.querySelector(".b3-menu").classList.remove("fn__none");
});
dockElement.addEventListener("mouseleave", () => {
dockElement.querySelector(".b3-menu").classList.add("fn__none");
});
}
document.querySelector("#status").addEventListener("click", (event) => {
let target = event.target as HTMLElement;

View file

@ -135,7 +135,10 @@ const dockToJSON = (dock: Dock) => {
if (data2.length > 0) {
json.push(data2);
}
return json;
return {
pin: dock.pin,
data: json
}
};
export const resetLayout = () => {
@ -169,10 +172,47 @@ export const exportLayout = (reload: boolean, cb?: () => void) => {
const JSONToDock = (json: any) => {
window.siyuan.layout.centerLayout = window.siyuan.layout.layout.children[1].children[1] as Layout;
window.siyuan.layout.topDock = new Dock({position: "Top", data: json.top});
window.siyuan.layout.leftDock = new Dock({position: "Left", data: json.left});
window.siyuan.layout.rightDock = new Dock({position: "Right", data: json.right});
window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: json.bottom});
// 历史数据兼容202306后可删除
let topData: { pin: boolean, data: IDockTab[][] }
if (!json.top.data) {
topData = {
pin: true,
data: json.top
}
} else {
topData = json.top;
}
let bottomData: { pin: boolean, data: IDockTab[][] }
if (!json.bottom.data) {
bottomData = {
pin: true,
data: json.bottom
}
} else {
bottomData = json.bottom;
}
let rightData: { pin: boolean, data: IDockTab[][] }
if (!json.right.data) {
rightData = {
pin: true,
data: json.right
}
} else {
rightData = json.right;
}
let leftData: { pin: boolean, data: IDockTab[][] }
if (!json.left.data) {
leftData = {
pin: true,
data: json.left
}
} else {
leftData = json.left;
}
window.siyuan.layout.topDock = new Dock({position: "Top", data: topData});
window.siyuan.layout.leftDock = new Dock({position: "Left", data: leftData});
window.siyuan.layout.rightDock = new Dock({position: "Right", data: rightData});
window.siyuan.layout.bottomDock = new Dock({position: "Bottom", data: bottomData});
};
export const JSONToCenter = (json: any, layout?: Layout | Wnd | Tab | Model, isStart = false) => {

View file

@ -96,6 +96,23 @@ export const globalShortcut = () => {
window.siyuan.hideBreadcrumb = false;
}
if (event.clientX < 43) {
if (!window.siyuan.layout.leftDock.pin) {
if (event.clientY > 32 &&
(window.siyuan.config.appearance.hideStatusBar ||
(!window.siyuan.config.appearance.hideStatusBar && event.clientY < window.innerHeight - 32))
) {
if (!hasClosestByClassName(event.target as HTMLElement, "b3-menu") &&
window.siyuan.layout.leftDock.layout.element.style.opacity !== "1") {
window.siyuan.layout.leftDock.layout.element.style.left = (window.siyuan.layout.leftDock.element.clientWidth + .5) + "px"
window.siyuan.layout.leftDock.layout.element.style.opacity = "1"
}
} else {
window.siyuan.layout.leftDock.hideDock();
}
}
}
const eventPath0 = event.composedPath()[0] as HTMLElement;
if (eventPath0 && eventPath0.nodeType !== 3 && eventPath0.classList.contains("protyle-wysiwyg") && eventPath0.style.paddingLeft) {
// 光标在编辑器右边也需要进行显示