mirror of
https://github.com/zadam/trilium.git
synced 2025-03-01 14:22:32 +01:00
closing panes
This commit is contained in:
parent
2f5d3729de
commit
5707b7e29a
@ -1,12 +1,12 @@
|
|||||||
import FlexContainer from "../widgets/containers/flex_container.js";
|
import FlexContainer from "../widgets/containers/flex_container.js";
|
||||||
import GlobalMenuWidget from "../widgets/global_menu.js";
|
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
||||||
import TabRowWidget from "../widgets/tab_row.js";
|
import TabRowWidget from "../widgets/tab_row.js";
|
||||||
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
||||||
import SidePaneContainer from "../widgets/containers/side_pane_container.js";
|
import SidePaneContainer from "../widgets/containers/side_pane_container.js";
|
||||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||||
import NoteTitleWidget from "../widgets/note_title.js";
|
import NoteTitleWidget from "../widgets/note_title.js";
|
||||||
import OwnedAttributeListWidget from "../widgets/type_property_widgets/owned_attribute_list.js";
|
import OwnedAttributeListWidget from "../widgets/type_property_widgets/owned_attribute_list.js";
|
||||||
import NoteActionsWidget from "../widgets/note_actions.js";
|
import NoteActionsWidget from "../widgets/buttons/note_actions.js";
|
||||||
import NoteDetailWidget from "../widgets/note_detail.js";
|
import NoteDetailWidget from "../widgets/note_detail.js";
|
||||||
import CollapsibleSectionContainer from "../widgets/containers/collapsible_section_container.js";
|
import CollapsibleSectionContainer from "../widgets/containers/collapsible_section_container.js";
|
||||||
import PromotedAttributesWidget from "../widgets/type_property_widgets/promoted_attributes.js";
|
import PromotedAttributesWidget from "../widgets/type_property_widgets/promoted_attributes.js";
|
||||||
@ -26,10 +26,12 @@ import RootContainer from "../widgets/containers/root_container.js";
|
|||||||
import NoteUpdateStatusWidget from "../widgets/note_update_status.js";
|
import NoteUpdateStatusWidget from "../widgets/note_update_status.js";
|
||||||
import SpacerWidget from "../widgets/spacer.js";
|
import SpacerWidget from "../widgets/spacer.js";
|
||||||
import QuickSearchWidget from "../widgets/quick_search.js";
|
import QuickSearchWidget from "../widgets/quick_search.js";
|
||||||
import ButtonWidget from "../widgets/button_widget.js";
|
import ButtonWidget from "../widgets/buttons/button_widget.js";
|
||||||
import ProtectedSessionStatusWidget from "../widgets/protected_session_status.js";
|
import ProtectedSessionStatusWidget from "../widgets/buttons/protected_session_status.js";
|
||||||
import PaneContainer from "../widgets/containers/pane_container.js";
|
import PaneContainer from "../widgets/containers/pane_container.js";
|
||||||
import SidebarToggleWidget from "../widgets/sidebar_toggle.js";
|
import SidebarToggleWidget from "../widgets/buttons/sidebar_toggle.js";
|
||||||
|
import CreatePaneButton from "../widgets/buttons/create_pane_button.js";
|
||||||
|
import ClosePaneButton from "../widgets/buttons/close_pane_button.js";
|
||||||
|
|
||||||
export default class DesktopLayout {
|
export default class DesktopLayout {
|
||||||
constructor(customWidgets) {
|
constructor(customWidgets) {
|
||||||
@ -90,12 +92,9 @@ export default class DesktopLayout {
|
|||||||
.overflowing()
|
.overflowing()
|
||||||
.child(new NoteIconWidget())
|
.child(new NoteIconWidget())
|
||||||
.child(new NoteTitleWidget())
|
.child(new NoteTitleWidget())
|
||||||
.child(new ButtonWidget()
|
.child(new SpacerWidget(1))
|
||||||
.icon("bx-window-open bx-rotate-90")
|
.child(new ClosePaneButton())
|
||||||
.title("Create new pane")
|
.child(new CreatePaneButton())
|
||||||
.titlePlacement("bottom")
|
|
||||||
.onClick(widget => widget.triggerCommand("openNewPane", { ntxId: widget.getNtxId() }))
|
|
||||||
)
|
|
||||||
)
|
)
|
||||||
.child(
|
.child(
|
||||||
new CollapsibleSectionContainer()
|
new CollapsibleSectionContainer()
|
||||||
|
@ -64,6 +64,11 @@ class NoteContext extends Component {
|
|||||||
return appContext.tabManager.noteContexts.filter(nc => nc.ntxId === this.ntxId || nc.mainNtxId === this.ntxId);
|
return appContext.tabManager.noteContexts.filter(nc => nc.ntxId === this.ntxId || nc.mainNtxId === this.ntxId);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isMainContext() {
|
||||||
|
// if null then this is a main context
|
||||||
|
return !this.mainNtxId;
|
||||||
|
}
|
||||||
|
|
||||||
getMainContext() {
|
getMainContext() {
|
||||||
if (this.mainNtxId) {
|
if (this.mainNtxId) {
|
||||||
return appContext.tabManager.getNoteContextById(this.mainNtxId);
|
return appContext.tabManager.getNoteContextById(this.mainNtxId);
|
||||||
|
@ -277,7 +277,7 @@ export default class TabManager extends Component {
|
|||||||
await this.openContextWithNote(noteId, true);
|
await this.openContextWithNote(noteId, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
activateNoteContext(ntxId, triggerEvent = true) {
|
async activateNoteContext(ntxId, triggerEvent = true) {
|
||||||
if (ntxId === this.activeNtxId) {
|
if (ntxId === this.activeNtxId) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -285,7 +285,7 @@ export default class TabManager extends Component {
|
|||||||
this.activeNtxId = ntxId;
|
this.activeNtxId = ntxId;
|
||||||
|
|
||||||
if (triggerEvent) {
|
if (triggerEvent) {
|
||||||
this.triggerEvent('activeContextChanged', {
|
await this.triggerEvent('activeContextChanged', {
|
||||||
noteContext: this.getNoteContextById(ntxId)
|
noteContext: this.getNoteContextById(ntxId)
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -296,20 +296,23 @@ export default class TabManager extends Component {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async removeNoteContext(ntxId) {
|
async removeNoteContext(ntxId) {
|
||||||
const mainNoteContextToRemove = this.getNoteContextById(ntxId).getMainContext();
|
const noteContextToRemove = this.getNoteContextById(ntxId);
|
||||||
|
|
||||||
// close dangling autocompletes after closing the tab
|
// close dangling autocompletes after closing the tab
|
||||||
$(".aa-input").autocomplete("close");
|
$(".aa-input").autocomplete("close");
|
||||||
|
|
||||||
const ntxIdsToRemove = mainNoteContextToRemove.getSubContexts().map(nc => nc.ntxId);
|
const ntxIdsToRemove = noteContextToRemove.getSubContexts().map(nc => nc.ntxId);
|
||||||
|
|
||||||
await this.triggerEvent('beforeTabRemove', { ntxIds: ntxIdsToRemove });
|
await this.triggerEvent('beforeTabRemove', { ntxIds: ntxIdsToRemove });
|
||||||
|
|
||||||
if (this.mainNoteContexts.length <= 1) {
|
if (!noteContextToRemove.isMainContext()) {
|
||||||
|
await this.activateNoteContext(noteContextToRemove.getMainContext().ntxId);
|
||||||
|
}
|
||||||
|
else if (this.mainNoteContexts.length <= 1) {
|
||||||
await this.openAndActivateEmptyTab();
|
await this.openAndActivateEmptyTab();
|
||||||
}
|
}
|
||||||
else if (ntxIdsToRemove.includes(this.activeNtxId)) {
|
else if (ntxIdsToRemove.includes(this.activeNtxId)) {
|
||||||
const idx = this.mainNoteContexts.findIndex(nc => nc.ntxId === mainNoteContextToRemove.ntxId);
|
const idx = this.mainNoteContexts.findIndex(nc => nc.ntxId === noteContextToRemove.ntxId);
|
||||||
|
|
||||||
if (idx === this.mainNoteContexts.length - 1) {
|
if (idx === this.mainNoteContexts.length - 1) {
|
||||||
this.activatePreviousTabCommand();
|
this.activatePreviousTabCommand();
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
import BasicWidget from "./basic_widget.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<span class="button-widget"
|
<span class="button-widget"
|
||||||
@ -8,7 +8,11 @@ const TPL = `
|
|||||||
</span>
|
</span>
|
||||||
`;
|
`;
|
||||||
|
|
||||||
export default class ButtonWidget extends BasicWidget {
|
export default class ButtonWidget extends NoteContextAwareWidget {
|
||||||
|
isEnabled() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
super();
|
super();
|
||||||
|
|
18
src/public/app/widgets/buttons/close_pane_button.js
Normal file
18
src/public/app/widgets/buttons/close_pane_button.js
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
import ButtonWidget from "./button_widget.js";
|
||||||
|
|
||||||
|
export default class ClosePaneButton extends ButtonWidget {
|
||||||
|
isEnabled() {
|
||||||
|
return super.isEnabled()
|
||||||
|
// main note context should not be closeable
|
||||||
|
&& this.noteContext && !!this.noteContext.mainNtxId;
|
||||||
|
}
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.icon("bx-x")
|
||||||
|
.title("Close this pane")
|
||||||
|
.titlePlacement("bottom")
|
||||||
|
.onClick(widget => widget.triggerCommand("closeThisPane", { ntxId: widget.getNtxId() }));
|
||||||
|
}
|
||||||
|
}
|
12
src/public/app/widgets/buttons/create_pane_button.js
Normal file
12
src/public/app/widgets/buttons/create_pane_button.js
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import ButtonWidget from "./button_widget.js";
|
||||||
|
|
||||||
|
export default class CreatePaneButton extends ButtonWidget {
|
||||||
|
constructor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.icon("bx-window-open bx-rotate-90")
|
||||||
|
.title("Create new pane")
|
||||||
|
.titlePlacement("bottom")
|
||||||
|
.onClick(widget => widget.triggerCommand("openNewPane", { ntxId: widget.getNtxId() }));
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
import BasicWidget from "./basic_widget.js";
|
import BasicWidget from "../basic_widget.js";
|
||||||
import utils from "../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="global-menu-wrapper">
|
<div class="global-menu-wrapper">
|
||||||
@ -105,7 +105,7 @@ export default class GlobalMenuWidget extends BasicWidget {
|
|||||||
this.overflowing();
|
this.overflowing();
|
||||||
|
|
||||||
this.$widget.find(".show-about-dialog-button").on('click',
|
this.$widget.find(".show-about-dialog-button").on('click',
|
||||||
() => import("../dialogs/about.js").then(d => d.showDialog()));
|
() => import("../../dialogs/about.js").then(d => d.showDialog()));
|
||||||
|
|
||||||
this.$widget.find(".logout-button").toggle(!utils.isElectron());
|
this.$widget.find(".logout-button").toggle(!utils.isElectron());
|
||||||
|
|
@ -1,6 +1,6 @@
|
|||||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||||
import protectedSessionService from "../services/protected_session.js";
|
import protectedSessionService from "../../services/protected_session.js";
|
||||||
import utils from "../services/utils.js";
|
import utils from "../../services/utils.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `
|
||||||
<div class="dropdown note-actions">
|
<div class="dropdown note-actions">
|
||||||
@ -114,11 +114,11 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
import('../dialogs/export.js').then(d => d.showDialog(this.noteContext.notePath, 'single'));
|
import('../../dialogs/export.js').then(d => d.showDialog(this.noteContext.notePath, 'single'));
|
||||||
});
|
});
|
||||||
|
|
||||||
this.$importNoteButton = this.$widget.find('.import-files-button');
|
this.$importNoteButton = this.$widget.find('.import-files-button');
|
||||||
this.$importNoteButton.on("click", () => import('../dialogs/import.js').then(d => d.showDialog(this.noteId)));
|
this.$importNoteButton.on("click", () => import('../../dialogs/import.js').then(d => d.showDialog(this.noteId)));
|
||||||
|
|
||||||
this.$protectButton = this.$widget.find(".protect-button");
|
this.$protectButton = this.$widget.find(".protect-button");
|
||||||
this.$protectButton.on('click', () => protectedSessionService.protectNote(this.noteId, true, false));
|
this.$protectButton.on('click', () => protectedSessionService.protectNote(this.noteId, true, false));
|
@ -1,5 +1,5 @@
|
|||||||
import ButtonWidget from "./button_widget.js";
|
import ButtonWidget from "./button_widget.js";
|
||||||
import protectedSessionHolder from "../services/protected_session_holder.js";
|
import protectedSessionHolder from "../../services/protected_session_holder.js";
|
||||||
|
|
||||||
export default class ProtectedSessionStatusWidget extends ButtonWidget {
|
export default class ProtectedSessionStatusWidget extends ButtonWidget {
|
||||||
doRender() {
|
doRender() {
|
@ -1,6 +1,6 @@
|
|||||||
import ButtonWidget from "./button_widget.js";
|
import ButtonWidget from "./button_widget.js";
|
||||||
import options from "../services/options.js";
|
import options from "../../services/options.js";
|
||||||
import splitService from "../services/split.js";
|
import splitService from "../../services/split.js";
|
||||||
|
|
||||||
export default class SidebarToggleWidget extends ButtonWidget {
|
export default class SidebarToggleWidget extends ButtonWidget {
|
||||||
refreshIcon() {
|
refreshIcon() {
|
@ -55,6 +55,10 @@ export default class PaneContainer extends FlexContainer {
|
|||||||
await noteContext.setEmpty();
|
await noteContext.setEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
closeThisPaneCommand({ntxId}) {
|
||||||
|
appContext.tabManager.removeNoteContext(ntxId);
|
||||||
|
}
|
||||||
|
|
||||||
activeContextChangedEvent() {
|
activeContextChangedEvent() {
|
||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
@ -63,6 +67,16 @@ export default class PaneContainer extends FlexContainer {
|
|||||||
this.refresh();
|
this.refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
noteContextRemovedEvent({ntxIds}) {
|
||||||
|
this.children = this.children.filter(c => !ntxIds.includes(c.ntxId));
|
||||||
|
|
||||||
|
for (const ntxId of ntxIds) {
|
||||||
|
this.$widget.find(`[data-ntx-id="${ntxId}"]`).remove();
|
||||||
|
|
||||||
|
delete this.widgets[ntxId];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async refresh() {
|
async refresh() {
|
||||||
this.toggleExt(true);
|
this.toggleExt(true);
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ const TPL = `
|
|||||||
<div class="note-title-container">
|
<div class="note-title-container">
|
||||||
<style>
|
<style>
|
||||||
.note-title-container {
|
.note-title-container {
|
||||||
flex-grow: 100;
|
flex-grow: 1000;
|
||||||
}
|
}
|
||||||
|
|
||||||
.note-title-container input.note-title {
|
.note-title-container input.note-title {
|
||||||
|
@ -1,67 +0,0 @@
|
|||||||
import options from "../services/options.js";
|
|
||||||
import splitService from "../services/split.js";
|
|
||||||
import BasicWidget from "./basic_widget.js";
|
|
||||||
|
|
||||||
const TPL = `
|
|
||||||
<div>
|
|
||||||
<style>
|
|
||||||
.hide-left-pane-button, .show-left-pane-button {
|
|
||||||
position: fixed;
|
|
||||||
bottom: 10px;
|
|
||||||
left: 10px;
|
|
||||||
z-index: 100;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
<button class="hide-left-pane-button btn btn-sm icon-button bx bx-chevrons-left" title="Hide sidebar"></button>
|
|
||||||
<button class="show-left-pane-button btn btn-sm icon-button bx bx-chevrons-right" title="Show sidebar"></button>
|
|
||||||
|
|
||||||
<button class="hide-right-pane-button btn btn-sm icon-button bx bx-chevrons-right" title="Hide sidebar"></button>
|
|
||||||
<button class="show-right-pane-button btn btn-sm icon-button bx bx-chevrons-left" title="Show sidebar"></button>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default class SidePaneToggles extends BasicWidget {
|
|
||||||
constructor() {
|
|
||||||
super();
|
|
||||||
|
|
||||||
this.paneVisible = {};
|
|
||||||
}
|
|
||||||
|
|
||||||
doRender() {
|
|
||||||
this.$widget = $(TPL);
|
|
||||||
|
|
||||||
this.$widget.find(".show-right-pane-button").on('click', () => this.toggleAndSave('right', true));
|
|
||||||
this.$widget.find(".hide-right-pane-button").on('click', () => this.toggleAndSave('right', false));
|
|
||||||
|
|
||||||
this.$widget.find(".show-left-pane-button").on('click', () => this.toggleAndSave('left', true));
|
|
||||||
this.$widget.find(".hide-left-pane-button").on('click', () => this.toggleAndSave('left', false));
|
|
||||||
|
|
||||||
this.$widget.css("contain", "none"); // this widget overflows so we need to override default containment
|
|
||||||
}
|
|
||||||
|
|
||||||
toggleSidebar(side, show) {
|
|
||||||
$(`#${side}-pane`).toggle(show);
|
|
||||||
this.$widget.find(`.show-${side}-pane-button`).toggle(!show);
|
|
||||||
this.$widget.find(`.hide-${side}-pane-button`).toggle(show);
|
|
||||||
|
|
||||||
this.paneVisible[side] = show;
|
|
||||||
}
|
|
||||||
|
|
||||||
async toggleAndSave(side, show) {
|
|
||||||
await options.save(`${side}PaneVisible`, show.toString());
|
|
||||||
|
|
||||||
this.toggleSidebar(side, show);
|
|
||||||
|
|
||||||
splitService.setupSplit(this.paneVisible.left, this.paneVisible.right);
|
|
||||||
|
|
||||||
this.triggerEvent('sidebarVisibilityChanged', {side, show});
|
|
||||||
}
|
|
||||||
|
|
||||||
initialRenderCompleteEvent() {
|
|
||||||
this.toggleSidebar('left', options.is('leftPaneVisible'));
|
|
||||||
this.toggleSidebar('right', options.is('rightPaneVisible'));
|
|
||||||
|
|
||||||
splitService.setupSplit(this.paneVisible.left, this.paneVisible.right);
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,17 +1,16 @@
|
|||||||
import BasicWidget from "./basic_widget.js";
|
import BasicWidget from "./basic_widget.js";
|
||||||
|
|
||||||
const TPL = `
|
const TPL = `<div class="spacer"></div>`;
|
||||||
<div class="spacer">
|
|
||||||
<style>
|
|
||||||
.spacer {
|
|
||||||
flex-grow: 1000;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default class SpacerWidget extends BasicWidget {
|
export default class SpacerWidget extends BasicWidget {
|
||||||
|
constructor(growIndex = 1000) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.growIndex = growIndex;
|
||||||
|
}
|
||||||
|
|
||||||
doRender() {
|
doRender() {
|
||||||
this.$widget = $(TPL);
|
this.$widget = $(TPL);
|
||||||
|
this.$widget.css("flex-grow", this.growIndex)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user