- {event.metadataEntries.map(({ key, value }, index) => {
- const hasDuplicate = ((key.length > 0 ? countedMetadata[key] : undefined) ?? 0) > 1;
- return (
-
-
{
- updateMetadata(index, "key", evt.currentTarget.value);
- }}
- />
- {
- updateMetadata(index, "value", evt.currentTarget.value);
- }}
- />
-
- {
- addRow(index);
+
+
Metadata
+
+ {event.metadataEntries.map(({ key, value }, index) => {
+ const hasDuplicate = ((key.length > 0 ? countedMetadata[key] : undefined) ?? 0) > 1;
+ return (
+
+
{
+ updateMetadata(index, "key", evt.currentTarget.value);
}}
- >
-
-
- {
- removeRow(index);
+ />
+ {
+ updateMetadata(index, "value", evt.currentTarget.value);
}}
- style={{ visibility: event.metadataEntries.length > 1 ? "visible" : "hidden" }}
- >
-
-
-
-
- );
- })}
+ />
+
+ {
+ addRow(index);
+ }}
+ >
+
+
+ {
+ removeRow(index);
+ }}
+ style={{
+ visibility: event.metadataEntries.length > 1 ? "visible" : "hidden",
+ }}
+ >
+
+
+
+
+ );
+ })}
+
-
+
+ {duplicateKey && (
+
+ Duplicate key {duplicateKey[0]}
+
+ )}
+ {createdEvent.error?.message && (
+
+ {createdEvent.error.message}
+
+ )}
- {duplicateKey &&
Duplicate key {duplicateKey[0]}}
- {createdEvent.error?.message &&
{createdEvent.error.message}}
);
}
diff --git a/packages/studio-base/src/components/CssBaseline.stories.tsx b/packages/studio-base/src/components/CssBaseline.stories.tsx
index 0e4ac64ff8..0b1c2bcd4b 100644
--- a/packages/studio-base/src/components/CssBaseline.stories.tsx
+++ b/packages/studio-base/src/components/CssBaseline.stories.tsx
@@ -27,28 +27,3 @@ export const Scrollbars: StoryObj = {
);
},
};
-
-export const FontFeatureSettings: StoryObj = {
- render: () => {
- // See https://github.com/foxglove/studio/pull/5113#discussion_r1106619194
- return (
-
- cv08: I
-
- cv10: G
-
- 显示时间戳在
-
- );
- },
-};
-
-export const FontFeatureSettingsChinese: StoryObj = {
- ...FontFeatureSettings,
- parameters: { forceLanguage: "zh" },
-};
-
-export const FontFeatureSettingsJapanese: StoryObj = {
- ...FontFeatureSettings,
- parameters: { forceLanguage: "ja" },
-};
diff --git a/packages/studio-base/src/components/CssBaseline.tsx b/packages/studio-base/src/components/CssBaseline.tsx
index 8bb37d4878..d9a56e21e9 100644
--- a/packages/studio-base/src/components/CssBaseline.tsx
+++ b/packages/studio-base/src/components/CssBaseline.tsx
@@ -76,6 +76,9 @@ const useStyles = makeStyles()(({ palette, typography }) => ({
canvas: {
outline: "none",
},
+ th: {
+ textAlign: "inherit",
+ },
// mosaic styling
".mosaic": {
diff --git a/packages/studio-base/src/components/CurrentLayoutLocalStorageSyncAdapter.tsx b/packages/studio-base/src/components/CurrentLayoutLocalStorageSyncAdapter.tsx
index 516725764d..4cfce99515 100644
--- a/packages/studio-base/src/components/CurrentLayoutLocalStorageSyncAdapter.tsx
+++ b/packages/studio-base/src/components/CurrentLayoutLocalStorageSyncAdapter.tsx
@@ -7,6 +7,7 @@ import { useEffect } from "react";
import { useDebounce } from "use-debounce";
import Log from "@foxglove/log";
+import { LOCAL_STORAGE_STUDIO_LAYOUT_KEY } from "@foxglove/studio-base/constants/localStorageKeys";
import {
LayoutState,
useCurrentLayoutActions,
@@ -23,8 +24,6 @@ function selectLayoutData(state: LayoutState) {
const log = Log.getLogger(__filename);
-const KEY = "studio.layout";
-
export function CurrentLayoutLocalStorageSyncAdapter(): JSX.Element {
const { selectedSource } = usePlayerSelection();
@@ -46,13 +45,13 @@ export function CurrentLayoutLocalStorageSyncAdapter(): JSX.Element {
const serializedLayoutData = JSON.stringify(debouncedLayoutData);
assert(serializedLayoutData);
- localStorage.setItem(KEY, serializedLayoutData);
+ localStorage.setItem(LOCAL_STORAGE_STUDIO_LAYOUT_KEY, serializedLayoutData);
}, [debouncedLayoutData]);
useEffect(() => {
- log.debug(`Reading layout from local storage: ${KEY}`);
+ log.debug(`Reading layout from local storage: ${LOCAL_STORAGE_STUDIO_LAYOUT_KEY}`);
- const serializedLayoutData = localStorage.getItem(KEY);
+ const serializedLayoutData = localStorage.getItem(LOCAL_STORAGE_STUDIO_LAYOUT_KEY);
if (serializedLayoutData) {
log.debug("Restoring layout from local storage");
diff --git a/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx b/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx
index 118a82ef54..934c6fe3cd 100644
--- a/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx
+++ b/packages/studio-base/src/components/DataSourceDialog/DataSourceDialog.tsx
@@ -4,7 +4,7 @@
import CloseIcon from "@mui/icons-material/Close";
import { Dialog, IconButton } from "@mui/material";
-import { useCallback, useLayoutEffect, useMemo } from "react";
+import { useCallback, useLayoutEffect, useMemo, useRef } from "react";
import { useMountedState } from "react-use";
import { makeStyles } from "tss-react/mui";
@@ -63,7 +63,13 @@ export function DataSourceDialog(props: DataSourceDialogProps): JSX.Element {
dialogActions.dataSource.close();
}, [analytics, activeDataSource, dialogActions.dataSource]);
+ const prevActiveViewRef = useRef
();
useLayoutEffect(() => {
+ if (activeView === prevActiveViewRef.current) {
+ // Only run actions below when the active view actually changed
+ return;
+ }
+ prevActiveViewRef.current = activeView;
if (activeView === "file") {
dialogActions.openFile
.open()
diff --git a/packages/studio-base/src/components/DataSourceDialog/Start.stories.tsx b/packages/studio-base/src/components/DataSourceDialog/Start.stories.tsx
index 9567f66975..8f14eceb4a 100644
--- a/packages/studio-base/src/components/DataSourceDialog/Start.stories.tsx
+++ b/packages/studio-base/src/components/DataSourceDialog/Start.stories.tsx
@@ -5,10 +5,10 @@
import { StoryFn, StoryObj } from "@storybook/react";
import { ReactNode } from "react";
-import CurrentUserContext, {
+import BaseUserContext, {
CurrentUser,
- User,
-} from "@foxglove/studio-base/context/CurrentUserContext";
+ UserType,
+} from "@foxglove/studio-base/context/BaseUserContext";
import PlayerSelectionContext, {
PlayerSelection,
} from "@foxglove/studio-base/context/PlayerSelectionContext";
@@ -48,25 +48,6 @@ export default {
decorators: [Wrapper],
};
-function fakeUser(type: "free" | "paid" | "enterprise"): User {
- return {
- id: "user-1",
- email: "user@example.com",
- orgId: "org_id",
- orgDisplayName: "Orgalorg",
- orgSlug: "org",
- orgPaid: type === "paid" || type === "enterprise",
- org: {
- id: "org_id",
- slug: "org",
- displayName: "Orgalorg",
- isEnterprise: type === "enterprise",
- allowsUploads: true,
- supportsEdgeSites: type === "enterprise",
- },
- };
-}
-
// Connection
const playerSelection: PlayerSelection = {
selectSource: () => {},
@@ -93,8 +74,8 @@ const playerSelection: PlayerSelection = {
},
{
id: "5555",
- title: "2369",
- label: "Velodyne Lidar",
+ title: "ws://1.2.3.4:8765",
+ label: "Foxglove WebSocket",
},
{
id: "6666",
@@ -122,13 +103,16 @@ const playerSelection: PlayerSelection = {
],
};
-function CurrentUserWrapper(props: { children: ReactNode; user?: User | undefined }): JSX.Element {
+function CurrentUserWrapper(props: {
+ children: ReactNode;
+ userType?: UserType | undefined;
+}): JSX.Element {
const value: CurrentUser = {
- currentUser: props.user,
+ currentUserType: props.userType ?? "unauthenticated",
signIn: () => undefined,
signOut: async () => undefined,
};
- return {props.children};
+ return {props.children};
}
const Default = (): JSX.Element => ;
@@ -195,10 +179,8 @@ export const UserPrivateJapanese: StoryObj = {
export const UserAuthedFree: StoryObj = {
render: () => {
- const freeUser = fakeUser("free");
-
return (
-
+
@@ -222,10 +204,8 @@ export const UserAuthedFreeJapanese: StoryObj = {
export const UserAuthedPaid: StoryObj = {
render: () => {
- const freeUser = fakeUser("paid");
-
return (
-
+
diff --git a/packages/studio-base/src/components/DataSourceDialog/Start.tsx b/packages/studio-base/src/components/DataSourceDialog/Start.tsx
index 8e99d4f076..866a823dcc 100644
--- a/packages/studio-base/src/components/DataSourceDialog/Start.tsx
+++ b/packages/studio-base/src/components/DataSourceDialog/Start.tsx
@@ -13,10 +13,7 @@ import FoxgloveLogoText from "@foxglove/studio-base/components/FoxgloveLogoText"
import Stack from "@foxglove/studio-base/components/Stack";
import TextMiddleTruncate from "@foxglove/studio-base/components/TextMiddleTruncate";
import { useAnalytics } from "@foxglove/studio-base/context/AnalyticsContext";
-import {
- useCurrentUser,
- useCurrentUserType,
-} from "@foxglove/studio-base/context/CurrentUserContext";
+import { useCurrentUser } from "@foxglove/studio-base/context/BaseUserContext";
import { usePlayerSelection } from "@foxglove/studio-base/context/PlayerSelectionContext";
import { useWorkspaceActions } from "@foxglove/studio-base/context/Workspace/useWorkspaceActions";
import { AppEvent } from "@foxglove/studio-base/services/IAnalytics";
@@ -170,8 +167,7 @@ function SidebarItems(props: {
onSelectView: (newValue: DataSourceDialogItem) => void;
}): JSX.Element {
const { onSelectView } = props;
- const { signIn } = useCurrentUser();
- const currentUserType = useCurrentUserType();
+ const { currentUserType, signIn } = useCurrentUser();
const analytics = useAnalytics();
const { classes } = useStyles();
const { t } = useTranslation("openDialog");
@@ -198,7 +194,7 @@ function SidebarItems(props: {
{t("exploreSampleData")}