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 GlobalMenuWidget from "../widgets/global_menu.js";
|
||||
import GlobalMenuWidget from "../widgets/buttons/global_menu.js";
|
||||
import TabRowWidget from "../widgets/tab_row.js";
|
||||
import TitleBarButtonsWidget from "../widgets/title_bar_buttons.js";
|
||||
import SidePaneContainer from "../widgets/containers/side_pane_container.js";
|
||||
import NoteTreeWidget from "../widgets/note_tree.js";
|
||||
import NoteTitleWidget from "../widgets/note_title.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 CollapsibleSectionContainer from "../widgets/containers/collapsible_section_container.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 SpacerWidget from "../widgets/spacer.js";
|
||||
import QuickSearchWidget from "../widgets/quick_search.js";
|
||||
import ButtonWidget from "../widgets/button_widget.js";
|
||||
import ProtectedSessionStatusWidget from "../widgets/protected_session_status.js";
|
||||
import ButtonWidget from "../widgets/buttons/button_widget.js";
|
||||
import ProtectedSessionStatusWidget from "../widgets/buttons/protected_session_status.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 {
|
||||
constructor(customWidgets) {
|
||||
@ -90,12 +92,9 @@ export default class DesktopLayout {
|
||||
.overflowing()
|
||||
.child(new NoteIconWidget())
|
||||
.child(new NoteTitleWidget())
|
||||
.child(new ButtonWidget()
|
||||
.icon("bx-window-open bx-rotate-90")
|
||||
.title("Create new pane")
|
||||
.titlePlacement("bottom")
|
||||
.onClick(widget => widget.triggerCommand("openNewPane", { ntxId: widget.getNtxId() }))
|
||||
)
|
||||
.child(new SpacerWidget(1))
|
||||
.child(new ClosePaneButton())
|
||||
.child(new CreatePaneButton())
|
||||
)
|
||||
.child(
|
||||
new CollapsibleSectionContainer()
|
||||
|
@ -64,6 +64,11 @@ class NoteContext extends Component {
|
||||
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() {
|
||||
if (this.mainNtxId) {
|
||||
return appContext.tabManager.getNoteContextById(this.mainNtxId);
|
||||
|
@ -277,7 +277,7 @@ export default class TabManager extends Component {
|
||||
await this.openContextWithNote(noteId, true);
|
||||
}
|
||||
|
||||
activateNoteContext(ntxId, triggerEvent = true) {
|
||||
async activateNoteContext(ntxId, triggerEvent = true) {
|
||||
if (ntxId === this.activeNtxId) {
|
||||
return;
|
||||
}
|
||||
@ -285,7 +285,7 @@ export default class TabManager extends Component {
|
||||
this.activeNtxId = ntxId;
|
||||
|
||||
if (triggerEvent) {
|
||||
this.triggerEvent('activeContextChanged', {
|
||||
await this.triggerEvent('activeContextChanged', {
|
||||
noteContext: this.getNoteContextById(ntxId)
|
||||
});
|
||||
}
|
||||
@ -296,20 +296,23 @@ export default class TabManager extends Component {
|
||||
}
|
||||
|
||||
async removeNoteContext(ntxId) {
|
||||
const mainNoteContextToRemove = this.getNoteContextById(ntxId).getMainContext();
|
||||
const noteContextToRemove = this.getNoteContextById(ntxId);
|
||||
|
||||
// close dangling autocompletes after closing the tab
|
||||
$(".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 });
|
||||
|
||||
if (this.mainNoteContexts.length <= 1) {
|
||||
if (!noteContextToRemove.isMainContext()) {
|
||||
await this.activateNoteContext(noteContextToRemove.getMainContext().ntxId);
|
||||
}
|
||||
else if (this.mainNoteContexts.length <= 1) {
|
||||
await this.openAndActivateEmptyTab();
|
||||
}
|
||||
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) {
|
||||
this.activatePreviousTabCommand();
|
||||
|
@ -1,4 +1,4 @@
|
||||
import BasicWidget from "./basic_widget.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
|
||||
const TPL = `
|
||||
<span class="button-widget"
|
||||
@ -8,7 +8,11 @@ const TPL = `
|
||||
</span>
|
||||
`;
|
||||
|
||||
export default class ButtonWidget extends BasicWidget {
|
||||
export default class ButtonWidget extends NoteContextAwareWidget {
|
||||
isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
constructor() {
|
||||
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 utils from "../services/utils.js";
|
||||
import BasicWidget from "../basic_widget.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="global-menu-wrapper">
|
||||
@ -105,7 +105,7 @@ export default class GlobalMenuWidget extends BasicWidget {
|
||||
this.overflowing();
|
||||
|
||||
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());
|
||||
|
@ -1,6 +1,6 @@
|
||||
import NoteContextAwareWidget from "./note_context_aware_widget.js";
|
||||
import protectedSessionService from "../services/protected_session.js";
|
||||
import utils from "../services/utils.js";
|
||||
import NoteContextAwareWidget from "../note_context_aware_widget.js";
|
||||
import protectedSessionService from "../../services/protected_session.js";
|
||||
import utils from "../../services/utils.js";
|
||||
|
||||
const TPL = `
|
||||
<div class="dropdown note-actions">
|
||||
@ -114,11 +114,11 @@ export default class NoteActionsWidget extends NoteContextAwareWidget {
|
||||
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.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.on('click', () => protectedSessionService.protectNote(this.noteId, true, false));
|
@ -1,5 +1,5 @@
|
||||
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 {
|
||||
doRender() {
|
@ -1,6 +1,6 @@
|
||||
import ButtonWidget from "./button_widget.js";
|
||||
import options from "../services/options.js";
|
||||
import splitService from "../services/split.js";
|
||||
import options from "../../services/options.js";
|
||||
import splitService from "../../services/split.js";
|
||||
|
||||
export default class SidebarToggleWidget extends ButtonWidget {
|
||||
refreshIcon() {
|
@ -55,6 +55,10 @@ export default class PaneContainer extends FlexContainer {
|
||||
await noteContext.setEmpty();
|
||||
}
|
||||
|
||||
closeThisPaneCommand({ntxId}) {
|
||||
appContext.tabManager.removeNoteContext(ntxId);
|
||||
}
|
||||
|
||||
activeContextChangedEvent() {
|
||||
this.refresh();
|
||||
}
|
||||
@ -63,6 +67,16 @@ export default class PaneContainer extends FlexContainer {
|
||||
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() {
|
||||
this.toggleExt(true);
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ const TPL = `
|
||||
<div class="note-title-container">
|
||||
<style>
|
||||
.note-title-container {
|
||||
flex-grow: 100;
|
||||
flex-grow: 1000;
|
||||
}
|
||||
|
||||
.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";
|
||||
|
||||
const TPL = `
|
||||
<div class="spacer">
|
||||
<style>
|
||||
.spacer {
|
||||
flex-grow: 1000;
|
||||
}
|
||||
</style>
|
||||
</div>
|
||||
`;
|
||||
const TPL = `<div class="spacer"></div>`;
|
||||
|
||||
export default class SpacerWidget extends BasicWidget {
|
||||
constructor(growIndex = 1000) {
|
||||
super();
|
||||
|
||||
this.growIndex = growIndex;
|
||||
}
|
||||
|
||||
doRender() {
|
||||
this.$widget = $(TPL);
|
||||
this.$widget.css("flex-grow", this.growIndex)
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user