/
vshmidt
/
streamlit
Обзор
Документация
Войти
/
vshmidt
/
streamlit
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
develop
frontend/app/src/util/AppNavigation.ts
219 строк
6 KB
Ken McGrady
Update copyright header to 2026 (#13491)
02 янв 2026, 16:21
Не верифицирован
02 янв 2026, 16:21
374540a
Код
Авторство
О чём код?
/** * Copyright (c) Streamlit Inc. (2018-2022) Snowflake Inc. (2022-2026) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import { AppRoot, HostCommunicationManager } from "@streamlit/lib" import { IAppPage, Navigation, NewSession, PageConfig, } from "@streamlit/protobuf" interface AppNavigationState { expandSidebarNav: boolean hideSidebarNav: boolean appPages: IAppPage[] currentPageScriptHash: string navSections: string[] } export type MaybeStateUpdate = | [Partial<AppNavigationState>, () => void] | undefined export type PageUrlUpdateCallback = ( mainPageName: string, newPageName: string, isViewingMainPage: boolean ) => void export type PageNotFoundCallback = (pageName?: string) => void export type SetIconCallback = (icon: string) => void function getTitle(pageName: string): string { if (!pageName) { return "Streamlit" } return pageName } export class AppNavigation { readonly hostCommunicationMgr: HostCommunicationManager readonly onUpdatePageUrl: PageUrlUpdateCallback readonly onPageNotFound: PageNotFoundCallback readonly onPageIconChange: SetIconCallback isPageTitleSet: boolean isPageIconSet: boolean hasSetDefaultFavicon: boolean mainScriptHash: string | null appPages: IAppPage[] mainPage: IAppPage | null hideSidebarNav: boolean | null constructor( hostCommunicationMgr: HostCommunicationManager, onUpdatePageUrl: PageUrlUpdateCallback, onPageNotFound: PageNotFoundCallback, onPageIconChange: SetIconCallback ) { this.hostCommunicationMgr = hostCommunicationMgr this.onUpdatePageUrl = onUpdatePageUrl this.onPageNotFound = onPageNotFound this.onPageIconChange = onPageIconChange this.isPageIconSet = false this.isPageTitleSet = false this.hasSetDefaultFavicon = false this.mainScriptHash = null this.appPages = [] this.mainPage = null this.hideSidebarNav = null } handleNewSession(newSession: NewSession): MaybeStateUpdate { // Reset flags only when script hash changes (new page in multi-page app) if (this.mainScriptHash !== newSession.mainScriptHash) { this.isPageTitleSet = false this.isPageIconSet = false this.hasSetDefaultFavicon = false } this.mainScriptHash = newSession.mainScriptHash // Initialize to the config value if provided if (this.hideSidebarNav === null) { this.hideSidebarNav = newSession.config?.hideSidebarNav ?? null } // We do not know the page name, so use an empty string version document.title = getTitle("") return [ { // Set current page script hash to handle SPA case currentPageScriptHash: newSession.pageScriptHash, hideSidebarNav: this.hideSidebarNav ?? false, }, () => {}, ] } handleNavigation(navigationMsg: Navigation): MaybeStateUpdate { const { sections, position, appPages } = navigationMsg this.appPages = appPages this.hideSidebarNav = position === Navigation.Position.HIDDEN const currentPageScriptHash = navigationMsg.pageScriptHash const currentPage = appPages.find( p => p.pageScriptHash === currentPageScriptHash ) as IAppPage const mainPage = appPages.find(p => p.isDefault) as IAppPage this.mainPage = mainPage const currentPageName = currentPage.urlPathname as string if (!this.isPageTitleSet) { const title = getTitle(currentPage.pageName as string) document.title = title this.hostCommunicationMgr.sendMessageToHost({ type: "SET_PAGE_TITLE", title: currentPage.pageName ?? "", }) } if (!this.isPageIconSet && currentPage.icon) { this.onPageIconChange(currentPage.icon) } this.onUpdatePageUrl( mainPage.urlPathname ?? "", currentPageName, currentPage.isDefault ?? false ) return [ { appPages, navSections: sections, hideSidebarNav: this.hideSidebarNav, expandSidebarNav: navigationMsg.expanded, currentPageScriptHash, }, () => { this.hostCommunicationMgr.sendMessageToHost({ type: "SET_APP_PAGES", appPages, }) this.hostCommunicationMgr.sendMessageToHost({ type: "SET_CURRENT_PAGE_NAME", // Make sure we don't send the official page name for the main page // This command is used to update the URL in the url bar, so the main page // should not have a page name in the URL. currentPageName: currentPage.isDefault ? "" : currentPageName, currentPageScriptHash, }) }, ] } handlePageNotFound(pageName: string): MaybeStateUpdate { this.onPageNotFound(pageName) return [ { currentPageScriptHash: this.mainScriptHash ?? "" }, () => { this.hostCommunicationMgr.sendMessageToHost({ type: "SET_CURRENT_PAGE_NAME", currentPageName: "", currentPageScriptHash: this.mainScriptHash ?? "", }) }, ] } findPageByUrlPath(pathname: string): IAppPage | null { return ( this.appPages.find(appPage => // The page name is embedded at the end of the URL path, and if not, we are in the main page. // See https://github.com/streamlit/streamlit/blob/1.19.0/frontend/src/App.tsx#L740 pathname.endsWith("/" + appPage.urlPathname) ) ?? this.mainPage ) } handlePageConfigChanged(pageConfig: PageConfig): void { // Make flags "sticky" - once set, they stay true for the session. // This ensures that multiple set_page_config calls don't reset the flags. if (pageConfig.favicon) { this.isPageIconSet = true } if (pageConfig.title) { this.isPageTitleSet = true } } clearPageElements(elements: AppRoot, mainScriptHash: string): AppRoot { return elements.filterMainScriptElements(mainScriptHash) } }