From c9f7ab3f72c61091a76f3c775f1057b7185c441f Mon Sep 17 00:00:00 2001 From: Josh Dover <1813008+joshdover@users.noreply.github.com> Date: Mon, 24 May 2021 20:00:45 +0200 Subject: [PATCH] Remove `chrome.navLinks.update` (#99633) --- ...ibana-plugin-core-public.chromenavlinks.md | 1 - ...lugin-core-public.chromenavlinks.update.md | 30 ------------ ...re-public.chromenavlinkupdateablefields.md | 12 ----- .../core/public/kibana-plugin-core-public.md | 1 - src/core/public/chrome/chrome_service.mock.ts | 1 - src/core/public/chrome/index.ts | 2 +- src/core/public/chrome/nav_links/index.ts | 2 +- src/core/public/chrome/nav_links/nav_link.ts | 12 ----- .../nav_links/nav_links_service.test.ts | 46 +------------------ .../chrome/nav_links/nav_links_service.ts | 34 +------------- src/core/public/index.ts | 2 - src/core/public/public.api.md | 7 --- x-pack/plugins/apm/public/plugin.ts | 9 ++-- .../plugins/apm/public/toggleAppLinkInNav.ts | 15 ------ x-pack/plugins/graph/common/check_license.ts | 7 ++- x-pack/plugins/graph/public/application.ts | 5 +- x-pack/plugins/graph/public/plugin.ts | 30 +++++++++--- .../graph/public/services/toggle_nav_link.ts | 27 ----------- x-pack/plugins/licensing/README.md | 10 +++- 19 files changed, 50 insertions(+), 203 deletions(-) delete mode 100644 docs/development/core/public/kibana-plugin-core-public.chromenavlinks.update.md delete mode 100644 docs/development/core/public/kibana-plugin-core-public.chromenavlinkupdateablefields.md delete mode 100644 x-pack/plugins/apm/public/toggleAppLinkInNav.ts delete mode 100644 x-pack/plugins/graph/public/services/toggle_nav_link.ts diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.md b/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.md index 2d879a468f587..c12fb45e6ab42 100644 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.md +++ b/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.md @@ -23,5 +23,4 @@ export interface ChromeNavLinks | [getNavLinks$()](./kibana-plugin-core-public.chromenavlinks.getnavlinks_.md) | Get an observable for a sorted list of navlinks. | | [has(id)](./kibana-plugin-core-public.chromenavlinks.has.md) | Check whether or not a navlink exists. | | [showOnly(id)](./kibana-plugin-core-public.chromenavlinks.showonly.md) | Remove all navlinks except the one matching the given id. | -| [update(id, values)](./kibana-plugin-core-public.chromenavlinks.update.md) | Update the navlink for the given id with the updated attributes. Returns the updated navlink or undefined if it does not exist. | diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.update.md b/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.update.md deleted file mode 100644 index 7948f2f8543fd..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavlinks.update.md +++ /dev/null @@ -1,30 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeNavLinks](./kibana-plugin-core-public.chromenavlinks.md) > [update](./kibana-plugin-core-public.chromenavlinks.update.md) - -## ChromeNavLinks.update() method - -> Warning: This API is now obsolete. -> -> Uses the property when registering your application with [ApplicationSetup.register()](./kibana-plugin-core-public.applicationsetup.register.md) instead. -> - -Update the navlink for the given id with the updated attributes. Returns the updated navlink or `undefined` if it does not exist. - -Signature: - -```typescript -update(id: string, values: ChromeNavLinkUpdateableFields): ChromeNavLink | undefined; -``` - -## Parameters - -| Parameter | Type | Description | -| --- | --- | --- | -| id | string | | -| values | ChromeNavLinkUpdateableFields | | - -Returns: - -`ChromeNavLink | undefined` - diff --git a/docs/development/core/public/kibana-plugin-core-public.chromenavlinkupdateablefields.md b/docs/development/core/public/kibana-plugin-core-public.chromenavlinkupdateablefields.md deleted file mode 100644 index 0445bb28bb355..0000000000000 --- a/docs/development/core/public/kibana-plugin-core-public.chromenavlinkupdateablefields.md +++ /dev/null @@ -1,12 +0,0 @@ - - -[Home](./index.md) > [kibana-plugin-core-public](./kibana-plugin-core-public.md) > [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) - -## ChromeNavLinkUpdateableFields type - - -Signature: - -```typescript -export declare type ChromeNavLinkUpdateableFields = Partial>; -``` diff --git a/docs/development/core/public/kibana-plugin-core-public.md b/docs/development/core/public/kibana-plugin-core-public.md index ae16c1c0e5887..3972f737f6618 100644 --- a/docs/development/core/public/kibana-plugin-core-public.md +++ b/docs/development/core/public/kibana-plugin-core-public.md @@ -154,7 +154,6 @@ The plugin integrates with the core system via lifecycle events: `setup` | [ChromeBreadcrumb](./kibana-plugin-core-public.chromebreadcrumb.md) | | | [ChromeHelpExtensionLinkBase](./kibana-plugin-core-public.chromehelpextensionlinkbase.md) | | | [ChromeHelpExtensionMenuLink](./kibana-plugin-core-public.chromehelpextensionmenulink.md) | | -| [ChromeNavLinkUpdateableFields](./kibana-plugin-core-public.chromenavlinkupdateablefields.md) | | | [FatalErrorsStart](./kibana-plugin-core-public.fatalerrorsstart.md) | FatalErrors stop the Kibana Public Core and displays a fatal error screen with details about the Kibana build and the error. | | [HttpStart](./kibana-plugin-core-public.httpstart.md) | See [HttpSetup](./kibana-plugin-core-public.httpsetup.md) | | [IToasts](./kibana-plugin-core-public.itoasts.md) | Methods for adding and removing global toast messages. See [ToastsApi](./kibana-plugin-core-public.toastsapi.md). | diff --git a/src/core/public/chrome/chrome_service.mock.ts b/src/core/public/chrome/chrome_service.mock.ts index ae9c58af69603..b624084258817 100644 --- a/src/core/public/chrome/chrome_service.mock.ts +++ b/src/core/public/chrome/chrome_service.mock.ts @@ -20,7 +20,6 @@ const createStartContractMock = () => { get: jest.fn(), getAll: jest.fn(), showOnly: jest.fn(), - update: jest.fn(), enableForcedAppSwitcherNavigation: jest.fn(), getForceAppSwitcherNavigation$: jest.fn(), }, diff --git a/src/core/public/chrome/index.ts b/src/core/public/chrome/index.ts index 73499a81f2220..dd7affcdbf7cd 100644 --- a/src/core/public/chrome/index.ts +++ b/src/core/public/chrome/index.ts @@ -16,7 +16,7 @@ export type { ChromeHelpExtensionMenuGitHubLink, } from './ui/header/header_help_menu'; export type { NavType } from './ui'; -export type { ChromeNavLink, ChromeNavLinks, ChromeNavLinkUpdateableFields } from './nav_links'; +export type { ChromeNavLink, ChromeNavLinks } from './nav_links'; export type { ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, diff --git a/src/core/public/chrome/nav_links/index.ts b/src/core/public/chrome/nav_links/index.ts index a35a512b2a842..e41799b9918a3 100644 --- a/src/core/public/chrome/nav_links/index.ts +++ b/src/core/public/chrome/nav_links/index.ts @@ -7,5 +7,5 @@ */ export { NavLinksService } from './nav_links_service'; -export type { ChromeNavLink, ChromeNavLinkUpdateableFields } from './nav_link'; +export type { ChromeNavLink } from './nav_link'; export type { ChromeNavLinks } from './nav_links_service'; diff --git a/src/core/public/chrome/nav_links/nav_link.ts b/src/core/public/chrome/nav_links/nav_link.ts index 65d59c59e9f75..87175ea465b7f 100644 --- a/src/core/public/chrome/nav_links/nav_link.ts +++ b/src/core/public/chrome/nav_links/nav_link.ts @@ -6,7 +6,6 @@ * Side Public License, v 1. */ -import { pick } from '@kbn/std'; import { AppCategory } from '../../'; /** @@ -81,11 +80,6 @@ export interface ChromeNavLink { readonly hidden?: boolean; } -/** @public */ -export type ChromeNavLinkUpdateableFields = Partial< - Pick ->; - export class NavLinkWrapper { public readonly id: string; public readonly properties: Readonly; @@ -98,10 +92,4 @@ export class NavLinkWrapper { this.id = properties.id; this.properties = Object.freeze(properties); } - - public update(newProps: ChromeNavLinkUpdateableFields) { - // Enforce limited properties at runtime for JS code - newProps = pick(newProps, ['disabled', 'hidden', 'url', 'href']); - return new NavLinkWrapper({ ...this.properties, ...newProps }); - } } diff --git a/src/core/public/chrome/nav_links/nav_links_service.test.ts b/src/core/public/chrome/nav_links/nav_links_service.test.ts index 74128aa798e7c..afb902fd6bd83 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.test.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.test.ts @@ -73,13 +73,10 @@ describe('NavLinksService', () => { const navLinkIds$ = start.getNavLinks$().pipe(map((links) => links.map((l) => l.id))); const emittedLinks: string[][] = []; navLinkIds$.subscribe((r) => emittedLinks.push(r)); - start.update('app1', { href: '/foo' }); + start.showOnly('app1'); service.stop(); - expect(emittedLinks).toEqual([ - ['app2', 'app1'], - ['app2', 'app1'], - ]); + expect(emittedLinks).toEqual([['app2', 'app1'], ['app1']]); }); it('completes when service is stopped', async () => { @@ -170,45 +167,6 @@ describe('NavLinksService', () => { }); }); - describe('#update()', () => { - it('updates the navlinks and returns the updated link', async () => { - expect(start.update('app2', { hidden: true })).toEqual( - expect.objectContaining({ - hidden: true, - id: 'app2', - order: -10, - title: 'App 2', - euiIconType: 'canvasApp', - }) - ); - const hiddenLinkIds = await start - .getNavLinks$() - .pipe( - take(1), - map((links) => links.filter((l) => l.hidden).map((l) => l.id)) - ) - .toPromise(); - expect(hiddenLinkIds).toEqual(['app2']); - }); - - it('returns undefined if link does not exist', () => { - expect(start.update('fake', { hidden: true })).toBeUndefined(); - }); - - it('keeps the updated link when availableApps are re-emitted', async () => { - start.update('app2', { hidden: true }); - mockAppService.applications$.next(mockAppService.applications$.value); - const hiddenLinkIds = await start - .getNavLinks$() - .pipe( - take(1), - map((links) => links.filter((l) => l.hidden).map((l) => l.id)) - ) - .toPromise(); - expect(hiddenLinkIds).toEqual(['app2']); - }); - }); - describe('#enableForcedAppSwitcherNavigation()', () => { it('flips #getForceAppSwitcherNavigation$()', async () => { await expect(start.getForceAppSwitcherNavigation$().pipe(take(1)).toPromise()).resolves.toBe( diff --git a/src/core/public/chrome/nav_links/nav_links_service.ts b/src/core/public/chrome/nav_links/nav_links_service.ts index 7a216d584044c..d41d8ae964d62 100644 --- a/src/core/public/chrome/nav_links/nav_links_service.ts +++ b/src/core/public/chrome/nav_links/nav_links_service.ts @@ -12,7 +12,7 @@ import { map, takeUntil } from 'rxjs/operators'; import { InternalApplicationStart } from '../../application'; import { HttpStart } from '../../http'; -import { ChromeNavLink, ChromeNavLinkUpdateableFields, NavLinkWrapper } from './nav_link'; +import { ChromeNavLink, NavLinkWrapper } from './nav_link'; import { toNavLink } from './to_nav_link'; interface StartDeps { @@ -58,18 +58,6 @@ export interface ChromeNavLinks { */ showOnly(id: string): void; - /** - * Update the navlink for the given id with the updated attributes. - * Returns the updated navlink or `undefined` if it does not exist. - * - * @deprecated Uses the {@link AppBase.updater$} property when registering - * your application with {@link ApplicationSetup.register} instead. - * - * @param id - * @param values - */ - update(id: string, values: ChromeNavLinkUpdateableFields): ChromeNavLink | undefined; - /** * Enable forced navigation mode, which will trigger a page refresh * when a nav link is clicked and only the hash is updated. @@ -109,6 +97,7 @@ export class NavLinksService { // now that availableApps$ is an observable, we need to keep record of all // manual link modifications to be able to re-apply then after every // availableApps$ changes. + // Only in use by `showOnly` API, can be removed once dashboard_mode is removed in 8.0 const linkUpdaters$ = new BehaviorSubject([]); const navLinks$ = new BehaviorSubject>(new Map()); @@ -153,25 +142,6 @@ export class NavLinksService { linkUpdaters$.next([...linkUpdaters$.value, updater]); }, - update(id: string, values: ChromeNavLinkUpdateableFields) { - if (!this.has(id)) { - return; - } - - const updater: LinksUpdater = (navLinks) => - new Map( - [...navLinks.entries()].map(([linkId, link]) => { - return [linkId, link.id === id ? link.update(values) : link] as [ - string, - NavLinkWrapper - ]; - }) - ); - - linkUpdaters$.next([...linkUpdaters$.value, updater]); - return this.get(id); - }, - enableForcedAppSwitcherNavigation() { forceAppSwitcherNavigation$.next(true); }, diff --git a/src/core/public/index.ts b/src/core/public/index.ts index 60d40aaf81036..129ae1c16f99b 100644 --- a/src/core/public/index.ts +++ b/src/core/public/index.ts @@ -41,7 +41,6 @@ import { ChromeNavControls, ChromeNavLink, ChromeNavLinks, - ChromeNavLinkUpdateableFields, ChromeDocTitle, ChromeStart, ChromeRecentlyAccessed, @@ -298,7 +297,6 @@ export type { ChromeNavControls, ChromeNavLink, ChromeNavLinks, - ChromeNavLinkUpdateableFields, ChromeDocTitle, ChromeRecentlyAccessed, ChromeRecentlyAccessedHistoryItem, diff --git a/src/core/public/public.api.md b/src/core/public/public.api.md index 449afa8869f6f..31e7a1e2321df 100644 --- a/src/core/public/public.api.md +++ b/src/core/public/public.api.md @@ -332,15 +332,8 @@ export interface ChromeNavLinks { getNavLinks$(): Observable>>; has(id: string): boolean; showOnly(id: string): void; - // Warning: (ae-unresolved-link) The @link reference could not be resolved: The package "kibana" does not have an export "AppBase" - // - // @deprecated - update(id: string, values: ChromeNavLinkUpdateableFields): ChromeNavLink | undefined; } -// @public (undocumented) -export type ChromeNavLinkUpdateableFields = Partial>; - // @public export interface ChromeRecentlyAccessed { // Warning: (ae-unresolved-link) The @link reference could not be resolved: No member was found with name "basePath" diff --git a/x-pack/plugins/apm/public/plugin.ts b/x-pack/plugins/apm/public/plugin.ts index b493363d98f7a..b76849ccf3011 100644 --- a/x-pack/plugins/apm/public/plugin.ts +++ b/x-pack/plugins/apm/public/plugin.ts @@ -9,6 +9,7 @@ import { i18n } from '@kbn/i18n'; import type { ConfigSchema } from '.'; import { AppMountParameters, + AppNavLinkStatus, CoreSetup, CoreStart, DEFAULT_APP_CATEGORIES, @@ -40,7 +41,6 @@ import type { } from '../../triggers_actions_ui/public'; import { registerApmAlerts } from './components/alerting/register_apm_alerts'; import { featureCatalogueEntry } from './featureCatalogueEntry'; -import { toggleAppLinkInNav } from './toggleAppLinkInNav'; export type ApmPluginSetup = ReturnType; @@ -193,6 +193,9 @@ export class ApmPlugin implements Plugin { order: 8500, euiIconType: 'logoObservability', category: DEFAULT_APP_CATEGORIES.observability, + navLinkStatus: config.ui.enabled + ? AppNavLinkStatus.default + : AppNavLinkStatus.hidden, meta: { keywords: [ 'RUM', @@ -231,7 +234,5 @@ export class ApmPlugin implements Plugin { return {}; } - public start(core: CoreStart, plugins: ApmPluginStartDeps) { - toggleAppLinkInNav(core, this.initializerContext.config.get()); - } + public start(core: CoreStart, plugins: ApmPluginStartDeps) {} } diff --git a/x-pack/plugins/apm/public/toggleAppLinkInNav.ts b/x-pack/plugins/apm/public/toggleAppLinkInNav.ts deleted file mode 100644 index 2e70cdd71ded6..0000000000000 --- a/x-pack/plugins/apm/public/toggleAppLinkInNav.ts +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { CoreStart } from 'kibana/public'; -import { ConfigSchema } from '.'; - -export function toggleAppLinkInNav(core: CoreStart, { ui }: ConfigSchema) { - if (ui.enabled === false) { - core.chrome.navLinks.update('apm', { hidden: true }); - } -} diff --git a/x-pack/plugins/graph/common/check_license.ts b/x-pack/plugins/graph/common/check_license.ts index ec43fac66551b..8357efbbba643 100644 --- a/x-pack/plugins/graph/common/check_license.ts +++ b/x-pack/plugins/graph/common/check_license.ts @@ -17,7 +17,7 @@ export function assertNever(x: never): never { export interface GraphLicenseInformation { showAppLink: boolean; enableAppLink: boolean; - message: string; + message?: string; } export function checkLicense(license: ILicense | undefined): GraphLicenseInformation { @@ -53,20 +53,19 @@ export function checkLicense(license: ILicense | undefined): GraphLicenseInforma return { showAppLink: true, enableAppLink: false, - message: check.message || '', + message: check.message, }; case 'invalid': case 'unavailable': return { showAppLink: false, enableAppLink: false, - message: check.message || '', + message: check.message, }; case 'valid': return { showAppLink: true, enableAppLink: true, - message: '', }; default: return assertNever(check.state); diff --git a/x-pack/plugins/graph/public/application.ts b/x-pack/plugins/graph/public/application.ts index acc3790a5ac6e..0b80e18f3fdb2 100644 --- a/x-pack/plugins/graph/public/application.ts +++ b/x-pack/plugins/graph/public/application.ts @@ -91,7 +91,10 @@ export const renderApp = ({ appBasePath, element, kibanaLegacy, ...deps }: Graph const licenseAllowsToShowThisPage = info.showAppLink && info.enableAppLink; if (!licenseAllowsToShowThisPage) { - deps.core.notifications.toasts.addDanger(info.message); + if (info.message) { + deps.core.notifications.toasts.addDanger(info.message); + } + // This has to happen in the next tick because otherwise the original navigation // bringing us to the graph app in the first place // never completes and the browser enters are redirect loop diff --git a/x-pack/plugins/graph/public/plugin.ts b/x-pack/plugins/graph/public/plugin.ts index d8f92e0134dce..4525b42b3feb4 100644 --- a/x-pack/plugins/graph/public/plugin.ts +++ b/x-pack/plugins/graph/public/plugin.ts @@ -6,9 +6,17 @@ */ import { i18n } from '@kbn/i18n'; -import { CoreSetup, CoreStart } from 'kibana/public'; -import { AppMountParameters, Plugin } from 'src/core/public'; -import { PluginInitializerContext } from 'kibana/public'; +import { BehaviorSubject } from 'rxjs'; +import { + AppNavLinkStatus, + AppUpdater, + CoreSetup, + CoreStart, + AppMountParameters, + Plugin, + PluginInitializerContext, + DEFAULT_APP_CATEGORIES, +} from '../../../../src/core/public'; import { Storage } from '../../../../src/plugins/kibana_utils/public'; import { @@ -18,7 +26,6 @@ import { import { NavigationPublicPluginStart as NavigationStart } from '../../../../src/plugins/navigation/public'; import { DataPublicPluginStart } from '../../../../src/plugins/data/public'; -import { toggleNavLink } from './services/toggle_nav_link'; import { LicensingPluginStart } from '../../licensing/public'; import { checkLicense } from '../common/check_license'; import { @@ -26,7 +33,6 @@ import { HomePublicPluginSetup, HomePublicPluginStart, } from '../../../../src/plugins/home/public'; -import { DEFAULT_APP_CATEGORIES } from '../../../../src/core/public'; import { ConfigSchema } from '../config'; import { SavedObjectsStart } from '../../../../src/plugins/saved_objects/public'; @@ -45,6 +51,8 @@ export interface GraphPluginStartDependencies { export class GraphPlugin implements Plugin { + private readonly appUpdater$ = new BehaviorSubject(() => ({})); + constructor(private initializerContext: PluginInitializerContext) {} setup(core: CoreSetup, { home }: GraphPluginSetupDependencies) { @@ -77,6 +85,7 @@ export class GraphPlugin appRoute: '/app/graph', euiIconType: 'logoKibana', category: DEFAULT_APP_CATEGORIES.kibana, + updater$: this.appUpdater$, mount: async (params: AppMountParameters) => { const [coreStart, pluginsStart] = await core.getStartServices(); coreStart.chrome.docTitle.change( @@ -112,7 +121,16 @@ export class GraphPlugin start(core: CoreStart, { home, licensing }: GraphPluginStartDependencies) { licensing.license$.subscribe((license) => { const licenseInformation = checkLicense(license); - toggleNavLink(licenseInformation, core.chrome.navLinks); + + this.appUpdater$.next(() => ({ + navLinkStatus: licenseInformation.showAppLink + ? licenseInformation.enableAppLink + ? AppNavLinkStatus.visible + : AppNavLinkStatus.disabled + : AppNavLinkStatus.hidden, + tooltip: licenseInformation.showAppLink ? licenseInformation.message : undefined, + })); + if (home && !licenseInformation.enableAppLink) { home.featureCatalogue.removeFeature('graph'); } diff --git a/x-pack/plugins/graph/public/services/toggle_nav_link.ts b/x-pack/plugins/graph/public/services/toggle_nav_link.ts deleted file mode 100644 index 364af0c277623..0000000000000 --- a/x-pack/plugins/graph/public/services/toggle_nav_link.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one - * or more contributor license agreements. Licensed under the Elastic License - * 2.0; you may not use this file except in compliance with the Elastic License - * 2.0. - */ - -import { ChromeNavLink, ChromeNavLinks } from 'kibana/public'; -import { GraphLicenseInformation } from '../../common/check_license'; - -type Mutable = { -readonly [P in keyof T]: T[P] }; -type ChromeNavLinkUpdate = Mutable>; - -export function toggleNavLink( - licenseInformation: GraphLicenseInformation, - navLinks: ChromeNavLinks -) { - const navLinkUpdates: ChromeNavLinkUpdate = { - hidden: !licenseInformation.showAppLink, - }; - if (licenseInformation.showAppLink) { - navLinkUpdates.disabled = !licenseInformation.enableAppLink; - navLinkUpdates.tooltip = licenseInformation.message; - } - - navLinks.update('graph', navLinkUpdates); -} diff --git a/x-pack/plugins/licensing/README.md b/x-pack/plugins/licensing/README.md index a058d42fe908b..3de1fe9cae425 100644 --- a/x-pack/plugins/licensing/README.md +++ b/x-pack/plugins/licensing/README.md @@ -84,13 +84,19 @@ class MyPlugin { import { LicensingPluginSetup } from '../licensing/public' class MyPlugin { setup(core: CoreSetup, deps: SetupDeps) { + const appUpdater$ = new BehaviorSubject(() => {}); + core.application.register({ + id: 'myApp', + updater$: appUpdater$, + }); + deps.licensing.license$.subscribe(license => { const { state, message } = license.check('myPlugin', 'gold') const hasRequiredLicense = state === 'valid'; const showLinks = hasRequiredLicense && license.getFeature('name').isAvailable; - chrome.navLinks.update('myPlugin', { - hidden: !showLinks + appUpdater$.next(() => { + navLinkStatus: showLinks ? AppNavLinkStatus.visible : AppNavLinkStatus.hidden }); }) }