claudeup 4.10.2 → 4.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/__tests__/plugin-setup.test.ts +300 -0
- package/src/__tests__/plugin-version-check.test.ts +762 -0
- package/src/prerunner/index.js +17 -0
- package/src/prerunner/index.ts +20 -0
- package/src/services/plugin-setup.js +88 -1
- package/src/services/plugin-setup.ts +99 -1
- package/src/services/plugin-version-check.js +257 -0
- package/src/services/plugin-version-check.ts +355 -0
- package/src/ui/App.js +96 -18
- package/src/ui/App.tsx +148 -62
- package/src/ui/screens/PluginsScreen.js +86 -13
- package/src/ui/screens/PluginsScreen.tsx +135 -24
- package/src/ui/state/DimensionsContext.js +8 -6
- package/src/ui/state/DimensionsContext.tsx +10 -1
|
@@ -38,11 +38,15 @@ import {
|
|
|
38
38
|
checkMissingDeps,
|
|
39
39
|
installPluginDeps,
|
|
40
40
|
} from "../../services/plugin-setup.js";
|
|
41
|
+
import { checkSinglePluginMismatch } from "../../services/plugin-version-check.js";
|
|
41
42
|
import {
|
|
42
43
|
buildPluginBrowserItems,
|
|
43
44
|
type PluginBrowserItem,
|
|
44
45
|
} from "../adapters/pluginsAdapter.js";
|
|
45
|
-
import {
|
|
46
|
+
import {
|
|
47
|
+
renderPluginRow,
|
|
48
|
+
renderPluginDetail,
|
|
49
|
+
} from "../renderers/pluginRenderers.js";
|
|
46
50
|
|
|
47
51
|
export function PluginsScreen() {
|
|
48
52
|
const { state, dispatch } = useApp();
|
|
@@ -180,15 +184,23 @@ export function PluginsScreen() {
|
|
|
180
184
|
}
|
|
181
185
|
|
|
182
186
|
if (event.name === "up" || event.name === "k") {
|
|
183
|
-
if (isSearchActive)
|
|
184
|
-
|
|
187
|
+
if (isSearchActive)
|
|
188
|
+
dispatch({ type: "SET_SEARCHING", isSearching: false });
|
|
189
|
+
dispatch({
|
|
190
|
+
type: "PLUGINS_SELECT",
|
|
191
|
+
index: Math.max(0, pluginsState.selectedIndex - 1),
|
|
192
|
+
});
|
|
185
193
|
return;
|
|
186
194
|
}
|
|
187
195
|
if (event.name === "down" || event.name === "j") {
|
|
188
|
-
if (isSearchActive)
|
|
196
|
+
if (isSearchActive)
|
|
197
|
+
dispatch({ type: "SET_SEARCHING", isSearching: false });
|
|
189
198
|
dispatch({
|
|
190
199
|
type: "PLUGINS_SELECT",
|
|
191
|
-
index: Math.min(
|
|
200
|
+
index: Math.min(
|
|
201
|
+
selectableItems.length - 1,
|
|
202
|
+
pluginsState.selectedIndex + 1,
|
|
203
|
+
),
|
|
192
204
|
});
|
|
193
205
|
return;
|
|
194
206
|
}
|
|
@@ -211,13 +223,21 @@ export function PluginsScreen() {
|
|
|
211
223
|
) {
|
|
212
224
|
const item = selectableItems[pluginsState.selectedIndex];
|
|
213
225
|
if (item?.kind === "category") {
|
|
214
|
-
dispatch({
|
|
226
|
+
dispatch({
|
|
227
|
+
type: "PLUGINS_TOGGLE_MARKETPLACE",
|
|
228
|
+
name: item.marketplace.name,
|
|
229
|
+
});
|
|
215
230
|
}
|
|
216
231
|
return;
|
|
217
232
|
}
|
|
218
233
|
|
|
219
234
|
if (isSearchActive) {
|
|
220
|
-
if (
|
|
235
|
+
if (
|
|
236
|
+
event.name.length === 1 &&
|
|
237
|
+
!event.ctrl &&
|
|
238
|
+
!event.meta &&
|
|
239
|
+
!/[0-9]/.test(event.name)
|
|
240
|
+
) {
|
|
221
241
|
dispatch({
|
|
222
242
|
type: "PLUGINS_SET_SEARCH",
|
|
223
243
|
query: pluginsState.searchQuery + event.name,
|
|
@@ -259,12 +279,43 @@ export function PluginsScreen() {
|
|
|
259
279
|
if (scope === "user") {
|
|
260
280
|
await saveGlobalInstalledPluginVersion(pluginId, version);
|
|
261
281
|
} else if (scope === "local") {
|
|
262
|
-
await saveLocalInstalledPluginVersion(
|
|
282
|
+
await saveLocalInstalledPluginVersion(
|
|
283
|
+
pluginId,
|
|
284
|
+
version,
|
|
285
|
+
state.projectPath,
|
|
286
|
+
);
|
|
263
287
|
} else {
|
|
264
288
|
await saveInstalledPluginVersion(pluginId, version, state.projectPath);
|
|
265
289
|
}
|
|
266
290
|
};
|
|
267
291
|
|
|
292
|
+
/**
|
|
293
|
+
* Check for version mismatch after a plugin update and warn the user.
|
|
294
|
+
* The [0] index bug in Claude Code means the update may not actually
|
|
295
|
+
* take effect if another project's entry is at index 0.
|
|
296
|
+
*/
|
|
297
|
+
const warnIfVersionMismatch = async (pluginId: string): Promise<void> => {
|
|
298
|
+
try {
|
|
299
|
+
const projectPath = state.projectPath || process.cwd();
|
|
300
|
+
const mismatch = await checkSinglePluginMismatch(pluginId, projectPath);
|
|
301
|
+
if (mismatch) {
|
|
302
|
+
await modal.message(
|
|
303
|
+
"Version Mismatch Warning",
|
|
304
|
+
`${pluginId} was updated to v${mismatch.currentProjectVersion} for this project, ` +
|
|
305
|
+
`but Claude Code will load v${mismatch.firstEntryVersion} due to a known bug.\n\n` +
|
|
306
|
+
`The plugin loader always uses the first entry in installed_plugins.json, ` +
|
|
307
|
+
`which belongs to another project.\n\n` +
|
|
308
|
+
`Bug: https://github.com/anthropics/claude-code/issues/45997\n\n` +
|
|
309
|
+
`To fix: open claudeup and use the version alignment tool, ` +
|
|
310
|
+
`or update the plugin in all projects to the same version.`,
|
|
311
|
+
"error",
|
|
312
|
+
);
|
|
313
|
+
}
|
|
314
|
+
} catch {
|
|
315
|
+
// Non-fatal: mismatch check is best-effort
|
|
316
|
+
}
|
|
317
|
+
};
|
|
318
|
+
|
|
268
319
|
// ── Action handlers ────────────────────────────────────────────────────────
|
|
269
320
|
|
|
270
321
|
const handleRefresh = async () => {
|
|
@@ -351,7 +402,10 @@ export function PluginsScreen() {
|
|
|
351
402
|
const pluginSource = await getPluginSourcePath(marketplace, pluginName);
|
|
352
403
|
if (!pluginSource) return true;
|
|
353
404
|
|
|
354
|
-
const requirements = await getPluginEnvRequirements(
|
|
405
|
+
const requirements = await getPluginEnvRequirements(
|
|
406
|
+
marketplace,
|
|
407
|
+
pluginSource,
|
|
408
|
+
);
|
|
355
409
|
if (requirements.length === 0) return true;
|
|
356
410
|
|
|
357
411
|
const existingEnvVars = await getMcpEnvVars(state.projectPath);
|
|
@@ -441,7 +495,8 @@ export function PluginsScreen() {
|
|
|
441
495
|
if (missing.pip?.length) parts.push(`pip: ${missing.pip.join(", ")}`);
|
|
442
496
|
if (missing.brew?.length) parts.push(`brew: ${missing.brew.join(", ")}`);
|
|
443
497
|
if (missing.npm?.length) parts.push(`npm: ${missing.npm.join(", ")}`);
|
|
444
|
-
if (missing.cargo?.length)
|
|
498
|
+
if (missing.cargo?.length)
|
|
499
|
+
parts.push(`cargo: ${missing.cargo.join(", ")}`);
|
|
445
500
|
|
|
446
501
|
const wantInstall = await modal.confirm(
|
|
447
502
|
"Install Dependencies?",
|
|
@@ -455,7 +510,9 @@ export function PluginsScreen() {
|
|
|
455
510
|
modal.hideModal();
|
|
456
511
|
|
|
457
512
|
if (result.failed.length > 0) {
|
|
458
|
-
const failMsg = result.failed
|
|
513
|
+
const failMsg = result.failed
|
|
514
|
+
.map((f) => `${f.pkg}: ${f.error}`)
|
|
515
|
+
.join("\n");
|
|
459
516
|
await modal.message(
|
|
460
517
|
"Partial Install",
|
|
461
518
|
`Installed: ${result.installed.length}\nFailed:\n${failMsg}`,
|
|
@@ -516,7 +573,11 @@ export function PluginsScreen() {
|
|
|
516
573
|
) => {
|
|
517
574
|
const installed = scope?.enabled;
|
|
518
575
|
const ver = scope?.version;
|
|
519
|
-
const hasUpdate =
|
|
576
|
+
const hasUpdate =
|
|
577
|
+
ver &&
|
|
578
|
+
latestVersion &&
|
|
579
|
+
ver !== latestVersion &&
|
|
580
|
+
latestVersion !== "0.0.0";
|
|
520
581
|
let label = installed ? `● ${name}` : `○ ${name}`;
|
|
521
582
|
label += ` (${desc})`;
|
|
522
583
|
if (ver) label += ` v${ver}`;
|
|
@@ -525,12 +586,25 @@ export function PluginsScreen() {
|
|
|
525
586
|
};
|
|
526
587
|
|
|
527
588
|
const scopeOptions = [
|
|
528
|
-
{
|
|
529
|
-
|
|
530
|
-
|
|
589
|
+
{
|
|
590
|
+
label: buildScopeLabel("User", plugin.userScope, "global"),
|
|
591
|
+
value: "user",
|
|
592
|
+
},
|
|
593
|
+
{
|
|
594
|
+
label: buildScopeLabel("Project", plugin.projectScope, "team"),
|
|
595
|
+
value: "project",
|
|
596
|
+
},
|
|
597
|
+
{
|
|
598
|
+
label: buildScopeLabel("Local", plugin.localScope, "private"),
|
|
599
|
+
value: "local",
|
|
600
|
+
},
|
|
531
601
|
];
|
|
532
602
|
|
|
533
|
-
const scopeValue = await modal.select(
|
|
603
|
+
const scopeValue = await modal.select(
|
|
604
|
+
plugin.name,
|
|
605
|
+
`Select scope to toggle:`,
|
|
606
|
+
scopeOptions,
|
|
607
|
+
);
|
|
534
608
|
if (scopeValue === null) return;
|
|
535
609
|
|
|
536
610
|
const selectedScope =
|
|
@@ -542,7 +616,11 @@ export function PluginsScreen() {
|
|
|
542
616
|
const isInstalledInScope = selectedScope?.enabled;
|
|
543
617
|
const installedVersion = selectedScope?.version;
|
|
544
618
|
const scopeLabel =
|
|
545
|
-
scopeValue === "user"
|
|
619
|
+
scopeValue === "user"
|
|
620
|
+
? "User"
|
|
621
|
+
: scopeValue === "project"
|
|
622
|
+
? "Project"
|
|
623
|
+
: "Local";
|
|
546
624
|
|
|
547
625
|
const hasUpdateInScope =
|
|
548
626
|
isInstalledInScope &&
|
|
@@ -585,6 +663,9 @@ export function PluginsScreen() {
|
|
|
585
663
|
if (action !== "install") {
|
|
586
664
|
modal.hideModal();
|
|
587
665
|
}
|
|
666
|
+
if (action === "update") {
|
|
667
|
+
await warnIfVersionMismatch(plugin.id);
|
|
668
|
+
}
|
|
588
669
|
fetchData();
|
|
589
670
|
} catch (error) {
|
|
590
671
|
modal.hideModal();
|
|
@@ -598,7 +679,8 @@ export function PluginsScreen() {
|
|
|
598
679
|
if (!item || item.kind !== "plugin" || !item.plugin.hasUpdate) return;
|
|
599
680
|
|
|
600
681
|
const plugin = item.plugin;
|
|
601
|
-
const scope: PluginScope =
|
|
682
|
+
const scope: PluginScope =
|
|
683
|
+
pluginsState.scope === "global" ? "user" : "project";
|
|
602
684
|
|
|
603
685
|
modal.loading(
|
|
604
686
|
`Updating ${plugin.name}…\nclaude plugin install ${plugin.id} --scope ${scope}`,
|
|
@@ -609,6 +691,7 @@ export function PluginsScreen() {
|
|
|
609
691
|
await saveVersionForScope(plugin.id, plugin.version, scope);
|
|
610
692
|
}
|
|
611
693
|
modal.hideModal();
|
|
694
|
+
await warnIfVersionMismatch(plugin.id);
|
|
612
695
|
fetchData();
|
|
613
696
|
} catch (error) {
|
|
614
697
|
modal.hideModal();
|
|
@@ -622,7 +705,9 @@ export function PluginsScreen() {
|
|
|
622
705
|
const updatable = pluginsState.plugins.data.filter((p) => p.hasUpdate);
|
|
623
706
|
if (updatable.length === 0) return;
|
|
624
707
|
|
|
625
|
-
const scope: PluginScope =
|
|
708
|
+
const scope: PluginScope =
|
|
709
|
+
pluginsState.scope === "global" ? "user" : "project";
|
|
710
|
+
const updatedPluginIds: string[] = [];
|
|
626
711
|
|
|
627
712
|
try {
|
|
628
713
|
for (let i = 0; i < updatable.length; i++) {
|
|
@@ -634,8 +719,13 @@ export function PluginsScreen() {
|
|
|
634
719
|
if (plugin.version) {
|
|
635
720
|
await saveVersionForScope(plugin.id, plugin.version, scope);
|
|
636
721
|
}
|
|
722
|
+
updatedPluginIds.push(plugin.id);
|
|
637
723
|
}
|
|
638
724
|
modal.hideModal();
|
|
725
|
+
// Check for mismatches on all updated plugins
|
|
726
|
+
for (const pluginId of updatedPluginIds) {
|
|
727
|
+
await warnIfVersionMismatch(pluginId);
|
|
728
|
+
}
|
|
639
729
|
fetchData();
|
|
640
730
|
} catch (error) {
|
|
641
731
|
modal.hideModal();
|
|
@@ -701,6 +791,9 @@ export function PluginsScreen() {
|
|
|
701
791
|
if (action !== "install") {
|
|
702
792
|
modal.hideModal();
|
|
703
793
|
}
|
|
794
|
+
if (action === "update") {
|
|
795
|
+
await warnIfVersionMismatch(plugin.id);
|
|
796
|
+
}
|
|
704
797
|
fetchData();
|
|
705
798
|
} catch (error) {
|
|
706
799
|
modal.hideModal();
|
|
@@ -745,8 +838,14 @@ export function PluginsScreen() {
|
|
|
745
838
|
"Save to scope",
|
|
746
839
|
"Where should this profile be saved?",
|
|
747
840
|
[
|
|
748
|
-
{
|
|
749
|
-
|
|
841
|
+
{
|
|
842
|
+
label: "User — ~/.claude/profiles.json (available everywhere)",
|
|
843
|
+
value: "user",
|
|
844
|
+
},
|
|
845
|
+
{
|
|
846
|
+
label: "Project — .claude/profiles.json (shared with team via git)",
|
|
847
|
+
value: "project",
|
|
848
|
+
},
|
|
750
849
|
],
|
|
751
850
|
);
|
|
752
851
|
if (scopeChoice === null) return;
|
|
@@ -808,7 +907,13 @@ export function PluginsScreen() {
|
|
|
808
907
|
const plugins: PluginInfo[] =
|
|
809
908
|
pluginsState.plugins.status === "success" ? pluginsState.plugins.data : [];
|
|
810
909
|
const installedCount = plugins.filter((p) => p.enabled).length;
|
|
811
|
-
const updateCount = plugins.filter(
|
|
910
|
+
const updateCount = plugins.filter(
|
|
911
|
+
(p) =>
|
|
912
|
+
p.hasUpdate &&
|
|
913
|
+
(p.userScope?.enabled ||
|
|
914
|
+
p.projectScope?.enabled ||
|
|
915
|
+
p.localScope?.enabled),
|
|
916
|
+
).length;
|
|
812
917
|
const subtitle = `${scopeLabel} │ ${installedCount} installed${updateCount > 0 ? ` │ ${updateCount} updates` : ""}`;
|
|
813
918
|
const searchPlaceholder = `${scopeLabel} │ ${installedCount} installed${updateCount > 0 ? ` │ ${updateCount} ⬆` : ""} │ / to search`;
|
|
814
919
|
|
|
@@ -833,11 +938,17 @@ export function PluginsScreen() {
|
|
|
833
938
|
getKey={(item) => item.id}
|
|
834
939
|
/>
|
|
835
940
|
{pluginsState.searchQuery && selectableItems.length === 0 && (
|
|
836
|
-
<EmptyFilterState
|
|
941
|
+
<EmptyFilterState
|
|
942
|
+
query={pluginsState.searchQuery}
|
|
943
|
+
entityName="plugins"
|
|
944
|
+
/>
|
|
837
945
|
)}
|
|
838
946
|
</box>
|
|
839
947
|
}
|
|
840
|
-
detailPanel={renderPluginDetail(
|
|
948
|
+
detailPanel={renderPluginDetail(
|
|
949
|
+
selectedItem,
|
|
950
|
+
pluginsState.collapsedMarketplaces,
|
|
951
|
+
)}
|
|
841
952
|
/>
|
|
842
953
|
);
|
|
843
954
|
}
|
|
@@ -7,7 +7,7 @@ const SCREEN_HEADER_HEIGHT = 4; // ScreenLayout: border + title row + status/sea
|
|
|
7
7
|
const SCREEN_FOOTER_HEIGHT = 2; // ScreenLayout: border-top + footer content
|
|
8
8
|
const APP_MARGINS = 1; // buffer for margins/padding
|
|
9
9
|
const PROGRESS_HEIGHT = 1; // when visible
|
|
10
|
-
function calculateDimensions(columns, rows, showProgress, showDebug, showUpdateBanner) {
|
|
10
|
+
function calculateDimensions(columns, rows, showProgress, showDebug, showUpdateBanner, transientBannerCount) {
|
|
11
11
|
const terminalWidth = columns;
|
|
12
12
|
const terminalHeight = rows;
|
|
13
13
|
// Calculate total available height for ScreenLayout (includes its header, panels, footer)
|
|
@@ -18,6 +18,7 @@ function calculateDimensions(columns, rows, showProgress, showDebug, showUpdateB
|
|
|
18
18
|
contentHeight -= 1;
|
|
19
19
|
if (showUpdateBanner)
|
|
20
20
|
contentHeight -= 1;
|
|
21
|
+
contentHeight -= transientBannerCount;
|
|
21
22
|
contentHeight = Math.max(10, contentHeight); // Minimum 10 lines for full layout
|
|
22
23
|
// Calculate available content width (accounting for padding)
|
|
23
24
|
const contentWidth = Math.max(40, terminalWidth - 4);
|
|
@@ -33,22 +34,23 @@ function calculateDimensions(columns, rows, showProgress, showDebug, showUpdateB
|
|
|
33
34
|
listPanelHeight,
|
|
34
35
|
};
|
|
35
36
|
}
|
|
36
|
-
export function DimensionsProvider({ children, showProgress = false, showDebug = false, showUpdateBanner = false, }) {
|
|
37
|
+
export function DimensionsProvider({ children, showProgress = false, showDebug = false, showUpdateBanner = false, transientBannerCount = 0, }) {
|
|
37
38
|
const renderer = useRenderer();
|
|
38
|
-
const [dimensions, setDimensions] = useState(() => calculateDimensions(renderer.width, renderer.height, showProgress, showDebug, showUpdateBanner));
|
|
39
|
+
const [dimensions, setDimensions] = useState(() => calculateDimensions(renderer.width, renderer.height, showProgress, showDebug, showUpdateBanner, transientBannerCount));
|
|
39
40
|
// Handle terminal resize
|
|
40
41
|
useOnResize((width, height) => {
|
|
41
|
-
setDimensions(calculateDimensions(width, height, showProgress, showDebug, showUpdateBanner));
|
|
42
|
+
setDimensions(calculateDimensions(width, height, showProgress, showDebug, showUpdateBanner, transientBannerCount));
|
|
42
43
|
});
|
|
43
|
-
// Update when showProgress/showDebug/showUpdateBanner changes
|
|
44
|
+
// Update when showProgress/showDebug/showUpdateBanner/transientBannerCount changes
|
|
44
45
|
useEffect(() => {
|
|
45
|
-
setDimensions(calculateDimensions(renderer.width, renderer.height, showProgress, showDebug, showUpdateBanner));
|
|
46
|
+
setDimensions(calculateDimensions(renderer.width, renderer.height, showProgress, showDebug, showUpdateBanner, transientBannerCount));
|
|
46
47
|
}, [
|
|
47
48
|
renderer.width,
|
|
48
49
|
renderer.height,
|
|
49
50
|
showProgress,
|
|
50
51
|
showDebug,
|
|
51
52
|
showUpdateBanner,
|
|
53
|
+
transientBannerCount,
|
|
52
54
|
]);
|
|
53
55
|
return (_jsx(DimensionsContext.Provider, { value: dimensions, children: children }));
|
|
54
56
|
}
|
|
@@ -30,6 +30,8 @@ interface DimensionsProviderProps {
|
|
|
30
30
|
showDebug?: boolean;
|
|
31
31
|
/** Whether update banner is visible */
|
|
32
32
|
showUpdateBanner?: boolean;
|
|
33
|
+
/** Number of transient banners (recovery, mismatch) currently visible */
|
|
34
|
+
transientBannerCount?: number;
|
|
33
35
|
}
|
|
34
36
|
|
|
35
37
|
function calculateDimensions(
|
|
@@ -38,6 +40,7 @@ function calculateDimensions(
|
|
|
38
40
|
showProgress: boolean,
|
|
39
41
|
showDebug: boolean,
|
|
40
42
|
showUpdateBanner: boolean,
|
|
43
|
+
transientBannerCount: number,
|
|
41
44
|
): Dimensions {
|
|
42
45
|
const terminalWidth = columns;
|
|
43
46
|
const terminalHeight = rows;
|
|
@@ -47,6 +50,7 @@ function calculateDimensions(
|
|
|
47
50
|
if (showProgress) contentHeight -= PROGRESS_HEIGHT;
|
|
48
51
|
if (showDebug) contentHeight -= 1;
|
|
49
52
|
if (showUpdateBanner) contentHeight -= 1;
|
|
53
|
+
contentHeight -= transientBannerCount;
|
|
50
54
|
contentHeight = Math.max(10, contentHeight); // Minimum 10 lines for full layout
|
|
51
55
|
|
|
52
56
|
// Calculate available content width (accounting for padding)
|
|
@@ -74,6 +78,7 @@ export function DimensionsProvider({
|
|
|
74
78
|
showProgress = false,
|
|
75
79
|
showDebug = false,
|
|
76
80
|
showUpdateBanner = false,
|
|
81
|
+
transientBannerCount = 0,
|
|
77
82
|
}: DimensionsProviderProps) {
|
|
78
83
|
const renderer = useRenderer();
|
|
79
84
|
|
|
@@ -84,6 +89,7 @@ export function DimensionsProvider({
|
|
|
84
89
|
showProgress,
|
|
85
90
|
showDebug,
|
|
86
91
|
showUpdateBanner,
|
|
92
|
+
transientBannerCount,
|
|
87
93
|
),
|
|
88
94
|
);
|
|
89
95
|
|
|
@@ -96,11 +102,12 @@ export function DimensionsProvider({
|
|
|
96
102
|
showProgress,
|
|
97
103
|
showDebug,
|
|
98
104
|
showUpdateBanner,
|
|
105
|
+
transientBannerCount,
|
|
99
106
|
),
|
|
100
107
|
);
|
|
101
108
|
});
|
|
102
109
|
|
|
103
|
-
// Update when showProgress/showDebug/showUpdateBanner changes
|
|
110
|
+
// Update when showProgress/showDebug/showUpdateBanner/transientBannerCount changes
|
|
104
111
|
useEffect(() => {
|
|
105
112
|
setDimensions(
|
|
106
113
|
calculateDimensions(
|
|
@@ -109,6 +116,7 @@ export function DimensionsProvider({
|
|
|
109
116
|
showProgress,
|
|
110
117
|
showDebug,
|
|
111
118
|
showUpdateBanner,
|
|
119
|
+
transientBannerCount,
|
|
112
120
|
),
|
|
113
121
|
);
|
|
114
122
|
}, [
|
|
@@ -117,6 +125,7 @@ export function DimensionsProvider({
|
|
|
117
125
|
showProgress,
|
|
118
126
|
showDebug,
|
|
119
127
|
showUpdateBanner,
|
|
128
|
+
transientBannerCount,
|
|
120
129
|
]);
|
|
121
130
|
|
|
122
131
|
return (
|