mirror of
https://github.com/Azure/cosmos-explorer.git
synced 2025-04-20 16:48:55 +01:00
146 lines
5.1 KiB
TypeScript
146 lines
5.1 KiB
TypeScript
import create, { UseStore } from "zustand";
|
|
import * as ViewModels from "../Contracts/ViewModels";
|
|
import { CollectionTabKind } from "../Contracts/ViewModels";
|
|
import NotebookTabV2 from "../Explorer/Tabs/NotebookV2Tab";
|
|
import TabsBase from "../Explorer/Tabs/TabsBase";
|
|
|
|
interface TabsState {
|
|
openedTabs: TabsBase[];
|
|
openedReactTabs: ReactTabKind[];
|
|
activeTab: TabsBase | undefined;
|
|
activeReactTab: ReactTabKind | undefined;
|
|
activateTab: (tab: TabsBase) => void;
|
|
activateNewTab: (tab: TabsBase) => void;
|
|
activateReactTab: (tabkind: ReactTabKind) => void;
|
|
updateTab: (tab: TabsBase) => void;
|
|
getTabs: (tabKind: ViewModels.CollectionTabKind, comparator?: (tab: TabsBase) => boolean) => TabsBase[];
|
|
refreshActiveTab: (comparator: (tab: TabsBase) => boolean) => void;
|
|
closeTabsByComparator: (comparator: (tab: TabsBase) => boolean) => void;
|
|
closeTab: (tab: TabsBase) => void;
|
|
closeAllNotebookTabs: (hardClose: boolean) => void;
|
|
openAndActivateReactTab: (tabKind: ReactTabKind) => void;
|
|
closeReactTab: (tabKind: ReactTabKind) => void;
|
|
}
|
|
|
|
export enum ReactTabKind {
|
|
Connect,
|
|
Home,
|
|
Quickstart,
|
|
}
|
|
|
|
export const useTabs: UseStore<TabsState> = create((set, get) => ({
|
|
openedTabs: [],
|
|
openedReactTabs: [ReactTabKind.Home],
|
|
activeTab: undefined,
|
|
activeReactTab: ReactTabKind.Home,
|
|
activateTab: (tab: TabsBase): void => {
|
|
if (get().openedTabs.some((openedTab) => openedTab.tabId === tab.tabId)) {
|
|
set({ activeTab: tab, activeReactTab: undefined });
|
|
tab.onActivate();
|
|
}
|
|
},
|
|
activateNewTab: (tab: TabsBase): void => {
|
|
set((state) => ({ openedTabs: [...state.openedTabs, tab], activeTab: tab, activeReactTab: undefined }));
|
|
tab.onActivate();
|
|
},
|
|
activateReactTab: (tabKind: ReactTabKind): void => set({ activeTab: undefined, activeReactTab: tabKind }),
|
|
updateTab: (tab: TabsBase) => {
|
|
if (get().activeTab?.tabId === tab.tabId) {
|
|
set({ activeTab: tab });
|
|
}
|
|
|
|
set((state) => ({
|
|
openedTabs: state.openedTabs.map((openedTab) => {
|
|
if (openedTab.tabId === tab.tabId) {
|
|
return tab;
|
|
}
|
|
return openedTab;
|
|
}),
|
|
}));
|
|
},
|
|
getTabs: (tabKind: ViewModels.CollectionTabKind, comparator?: (tab: TabsBase) => boolean): TabsBase[] =>
|
|
get().openedTabs.filter((tab) => tab.tabKind === tabKind && (!comparator || comparator(tab))),
|
|
refreshActiveTab: (comparator: (tab: TabsBase) => boolean): void => {
|
|
// ensures that the tab selects/highlights the right node based on resource tree expand/collapse state
|
|
const activeTab = get().activeTab;
|
|
activeTab && comparator(activeTab) && activeTab.onActivate();
|
|
},
|
|
closeTabsByComparator: (comparator: (tab: TabsBase) => boolean): void =>
|
|
get()
|
|
.openedTabs.filter(comparator)
|
|
.forEach((tab) => tab.onCloseTabButtonClick()),
|
|
closeTab: (tab: TabsBase): void => {
|
|
let tabIndex: number;
|
|
const { activeTab, openedTabs } = get();
|
|
const updatedTabs = openedTabs.filter((openedTab, index) => {
|
|
if (tab.tabId === openedTab.tabId) {
|
|
tabIndex = index;
|
|
return false;
|
|
}
|
|
return true;
|
|
});
|
|
if (updatedTabs.length === 0) {
|
|
set({ activeTab: undefined, activeReactTab: ReactTabKind.Home });
|
|
}
|
|
|
|
if (tab.tabId === activeTab.tabId && tabIndex !== -1) {
|
|
const tabToTheRight = updatedTabs[tabIndex];
|
|
const lastOpenTab = updatedTabs[updatedTabs.length - 1];
|
|
const newActiveTab = tabToTheRight ?? lastOpenTab;
|
|
set({ activeTab: newActiveTab });
|
|
if (newActiveTab) {
|
|
newActiveTab.onActivate();
|
|
}
|
|
}
|
|
|
|
set({ openedTabs: updatedTabs });
|
|
},
|
|
closeAllNotebookTabs: (hardClose): void => {
|
|
const isNotebook = (tabKind: CollectionTabKind): boolean => {
|
|
if (
|
|
tabKind === CollectionTabKind.Notebook ||
|
|
tabKind === CollectionTabKind.NotebookV2 ||
|
|
tabKind === CollectionTabKind.SchemaAnalyzer ||
|
|
tabKind === CollectionTabKind.Terminal
|
|
) {
|
|
return true;
|
|
}
|
|
return false;
|
|
};
|
|
|
|
const tabList = get().openedTabs;
|
|
if (tabList && tabList.length > 0) {
|
|
tabList.forEach((tab: NotebookTabV2) => {
|
|
const tabKind: CollectionTabKind = tab.tabKind;
|
|
if (tabKind && isNotebook(tabKind)) {
|
|
tab.onCloseTabButtonClick(hardClose);
|
|
}
|
|
});
|
|
|
|
if (get().openedTabs.length === 0) {
|
|
set({ activeTab: undefined, activeReactTab: ReactTabKind.Home });
|
|
}
|
|
}
|
|
},
|
|
openAndActivateReactTab: (tabKind: ReactTabKind) => {
|
|
if (get().openedReactTabs.indexOf(tabKind) === -1) {
|
|
set((state) => ({
|
|
openedReactTabs: [...state.openedReactTabs, tabKind],
|
|
}));
|
|
}
|
|
|
|
set({ activeTab: undefined, activeReactTab: tabKind });
|
|
},
|
|
closeReactTab: (tabKind: ReactTabKind) => {
|
|
const { activeReactTab, openedTabs, openedReactTabs } = get();
|
|
const updatedOpenedReactTabs = openedReactTabs.filter((tab: ReactTabKind) => tabKind !== tab);
|
|
if (activeReactTab === tabKind) {
|
|
openedTabs?.length > 0
|
|
? set({ activeTab: openedTabs[0], activeReactTab: undefined })
|
|
: set({ activeTab: undefined, activeReactTab: updatedOpenedReactTabs[0] });
|
|
}
|
|
|
|
set({ openedReactTabs: updatedOpenedReactTabs });
|
|
},
|
|
}));
|