import React from 'react' ; import { Provider } from 'polar-shared/src/util/Providers' ; import { createObservableStore , SetStore } from '../react/store/ObservableStore' ; import { arrayStream } from "polar-shared/src/util/ArrayStreams" ; export interface TabDescriptor { /**
     * The URL for this tab so that the router can be used with it.
     */ readonly url : string ; readonly title : string ; /**
     * An icon to show for this tab.
     */ readonly icon ? : React . ReactNode ; readonly component ? : React . ReactNode ; } interface IBrowserTabsStore { readonly activeTab : number | undefined ; readonly tabs : ReadonlyArray < TabDescriptor > ; } interface IBrowserTabsCallbacks { readonly setActiveTab : ( id : number ) => void ; readonly addTab : ( tabDescriptor : TabDescriptor ) => void ; readonly removeTab : ( id : number ) => void ; } function createInitialTabs ( ) { return [ { url : '/' , title : 'Polar: Document Repository' } , ] ; } const initialStore = { activeTab : 0 , tabs : createInitialTabs ( ) , } ; interface Mutation { readonly activeTab : number ; readonly tabs : ReadonlyArray < TabDescriptor > ; } interface Mutator { readonly doUpdate : ( mutation : Mutation ) => void ; } function mutatorFactory ( storeProvider , setStore ) { function doUpdate ( mutation ) { setStore ( mutation ) ; } return { doUpdate } ; } function useCallbacksFactory ( storeProvider , setStore , mutator ) { return React . useMemo ( ( ) : IBrowserTabsCallbacks => { function setActiveTab ( activeTab ) { const store = storeProvider ( ) ; setStore ( { ... store , activeTab } ) ; } function addTab ( tabDescriptor ) { const store = storeProvider ( ) ; function computeExistingTab ( ) { return arrayStream ( store . tabs ) . withIndex ( ) . filter ( current => current . value . url === tabDescriptor . url ) . first ( ) ; } function doTabMutation ( newStore ) { history . replaceState ( null , tabDescriptor . title , tabDescriptor . url ) ; setStore ( newStore ) ; } const existingTab = computeExistingTab ( ) ; if ( existingTab ) { doTabMutation ( { ... store , activeTab : existingTab . index } ) ; return ; } const tabs = [ ... store . tabs , tabDescriptor ] ; const activeTab = tabs . length - 1 ; doTabMutation ( { ... store , tabs , activeTab } ) ; } function removeTab ( id ) { const store = storeProvider ( ) ; function computeTabs ( ) { const tabs = [ ... store . tabs ] ; tabs . splice ( id , 1 ) ; return tabs ; } function computeActiveTab ( ) { if ( store . activeTab === id ) { return Math . max ( store . activeTab - 1 , 1 ) ; } return store . activeTab ; } const tabs = computeTabs ( ) ; const activeTab = computeActiveTab ( ) ; setStore ( { ... store , tabs , activeTab } ) ; } return { addTab , removeTab , setActiveTab } ; } , [ storeProvider , setStore ] ) ; } export function createBrowserTabsStore ( ) { return createObservableStore < IBrowserTabsStore , Mutator , IBrowserTabsCallbacks > ( { initialValue : initialStore , mutatorFactory , callbacksFactory : useCallbacksFactory } ) ; } export const [ BrowserTabsStoreProvider , useBrowserTabsStore , useBrowserTabsCallbacks ] = createBrowserTabsStore ( ) ; BrowserTabsStoreProvider . displayName = 'BrowserTabsStoreProvider' ;