vertical split tabs #394

This commit is contained in:
Jan Prochazka
2023-03-05 10:43:04 +01:00
parent 1061d2aba2
commit 2dadd1f437
8 changed files with 88 additions and 12 deletions

View File

@@ -28,6 +28,7 @@
import FontIcon from './icons/FontIcon.svelte';
import getElectron from './utility/getElectron';
import TabsContainer from './tabpanel/TabsContainer.svelte';
import MultiTabsContainer from './tabpanel/MultiTabsContainer.svelte';
$: currentThemeType = $currentThemeDefinition?.themeType == 'dark' ? 'theme-type-dark' : 'theme-type-light';
@@ -71,7 +72,7 @@
</div>
{/if}
<div class="tabs-container">
<TabsContainer />
<MultiTabsContainer />
</div>
{#if $selectedWidget && $visibleWidgetSideBar}
<div

View File

@@ -127,6 +127,7 @@
'icon compare': 'mdi mdi-compare',
'icon no-color': 'mdi mdi-format-color-marker-cancel',
'icon palette': 'mdi mdi-palette',
'icon split': 'mdi mdi-view-split-vertical',
'icon num-0': 'mdi mdi-numeric-0-circle',
'icon num-1': 'mdi mdi-numeric-1-circle',

View File

@@ -17,6 +17,8 @@ export interface TabDefinition {
tabid: string;
tabComponent: string;
tabOrder?: number;
multiTabIndex?: number;
visibleSecondary?: boolean;
}
export function writableWithStorage<T>(defaultValue: T, storageName) {

View File

@@ -0,0 +1,17 @@
<script>
import HorizontalSplitter from '../elements/HorizontalSplitter.svelte';
import { openedTabs } from '../stores';
import TabsContainer from './TabsContainer.svelte';
$: isLeft = !!$openedTabs.find(x => x.closedTime == null && !x.multiTabIndex);
$: isRight = !!$openedTabs.find(x => x.closedTime == null && x.multiTabIndex == 1);
</script>
<HorizontalSplitter hideFirst={!isLeft && isRight} isSplitter={isRight}>
<div class="container" slot="1">
<TabsContainer multiTabIndex={0} />
</div>
<div class="container" slot="2">
<TabsContainer multiTabIndex={1} />
</div>
</HorizontalSplitter>

View File

@@ -4,8 +4,12 @@
import TabContent from './TabContent.svelte';
import tabs from '../tabs';
export let multiTabIndex;
let mountedTabs = {};
$: selectedTab = $openedTabs.find(x => x.selected && x.closedTime == null);
$: selectedTab = $openedTabs.find(
x => (x.selected || x.visibleSecondary) && x.closedTime == null && (x.multiTabIndex || 0) == multiTabIndex
);
// cleanup closed tabs
$: {

View File

@@ -1,14 +1,15 @@
<script>
<script lang='ts'>
import TabRegister from './TabRegister.svelte';
import TabsPanel from './TabsPanel.svelte';
export let multiTabIndex;
</script>
<div class="tabs">
<TabsPanel />
<TabsPanel {multiTabIndex} />
</div>
<div class="content">
<TabRegister />
<TabRegister {multiTabIndex} />
</div>
<style>

View File

@@ -43,6 +43,8 @@
const newFiles = files.map(x => ({
...x,
closedTime: shouldShowTab(x) && closeCondition(x, active) ? new Date().getTime() : x.closedTime,
selected: false,
visibleSecondary: false,
}));
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
@@ -72,6 +74,8 @@
: files.map(x => ({
...x,
closedTime: shouldShowTab(x) && closeCondition(x) ? new Date().getTime() : x.closedTime,
selected: false,
visibleSecondary: false,
}));
if (newFiles.find(x => x.selected && shouldShowTab(x))) {
@@ -87,6 +91,17 @@
});
};
function splitTab(multiTabIndex) {
openedTabs.update(tabs => {
const secondaryIndex = _.findLastIndex(tabs, x => shouldShowTab(x) && !x.selected);
return tabs.map((x, i) => ({
...x,
multiTabIndex: x.selected ? 1 - multiTabIndex : x.multiTabIndex,
visibleSecondary: i == secondaryIndex,
}));
});
}
const closeTab = closeTabFunc((x, active) => x.tabid == active.tabid);
const closeAll = async () => {
const closeCandidates = getOpenedTabs()
@@ -101,6 +116,7 @@
...tab,
closedTime: shouldShowTab(tab) ? closedTime : tab.closedTime,
selected: false,
visibleSecondary: false,
}))
);
};
@@ -264,7 +280,10 @@
import TabCloseButton from '../elements/TabCloseButton.svelte';
import CloseTabModal from '../modals/CloseTabModal.svelte';
$: showTabFilterFunc = tab => shouldShowTab(tab, $lockedDatabaseMode, $currentDatabase);
export let multiTabIndex;
$: showTabFilterFunc = tab =>
shouldShowTab(tab, $lockedDatabaseMode, $currentDatabase) && (tab.multiTabIndex || 0) == multiTabIndex;
$: connectionList = useConnectionList();
$: currentDbKey =
@@ -287,6 +306,10 @@
$: scrollInViewTab($activeTabId);
$: filteredTabsFromAllParts = $openedTabs.filter(x => shouldShowTab(x));
$: allowSplitTab =
_.uniq(filteredTabsFromAllParts.map(x => x.multiTabIndex || 0)).length == 1 && filteredTabsFromAllParts.length >= 2;
let draggingTab = null;
let draggingTabTarget = null;
let draggingDbGroup = null;
@@ -540,7 +563,16 @@
</div>
{/each}
</div>
<div class="add-icon" on:click={() => newQuery({})} title="New query"><FontIcon icon="icon add" /></div>
<div class="icons-wrapper">
{#if allowSplitTab}
<div class="icon-button" on:click={() => splitTab(multiTabIndex)} title="Split window">
<FontIcon icon="icon split" />
</div>
{/if}
<div class="icon-button" on:click={() => newQuery({})} title="New query">
<FontIcon icon="icon add" />
</div>
</div>
</div>
<style>
@@ -551,7 +583,7 @@
right: 0;
bottom: 0;
}
.add-icon {
.icons-wrapper {
position: absolute;
right: 5px;
font-size: 20pt;
@@ -559,10 +591,13 @@
bottom: 0;
display: flex;
align-items: center;
display: flex;
}
.icon-button {
color: var(--theme-font-2);
cursor: pointer;
}
.add-icon:hover {
.icon-button:hover {
color: var(--theme-font-1);
}
.tabs {

View File

@@ -29,9 +29,24 @@ export function markTabSaved(tabid) {
}
export function setSelectedTabFunc(files, tabid) {
const oldSelected = files.find(x => x.selected);
const newSelected = files.find(x => x.tabid == tabid);
const changeVisibleSecondary = (oldSelected.multiTabIndex || 0) != (newSelected.multiTabIndex || 0);
return [
...(files || []).filter(x => x.tabid != tabid).map(x => ({ ...x, selected: false })),
...(files || []).filter(x => x.tabid == tabid).map(x => ({ ...x, selected: true })),
...(files || [])
.filter(x => x.tabid != tabid)
.map(x => ({
...x,
selected: false,
visibleSecondary: changeVisibleSecondary ? x.selected : x.visibleSecondary,
})),
...(files || [])
.filter(x => x.tabid == tabid)
.map(x => ({
...x,
selected: true,
visibleSecondary: false,
})),
];
}