This is an automated email from the ASF dual-hosted git repository.

bbovenzi pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git


The following commit(s) were added to refs/heads/main by this push:
     new 09fc45decf4 Centralize localStorage keys into a shared constants 
(#62310)
09fc45decf4 is described below

commit 09fc45decf409a99450cd2bc914ce93d0d7bd110
Author: Yeonguk Choo <[email protected]>
AuthorDate: Tue Feb 24 01:54:35 2026 +0900

    Centralize localStorage keys into a shared constants (#62310)
---
 .../src/components/DataTable/useTableUrlState.ts   |  6 +--
 .../src/airflow/ui/src/constants/localStorage.ts   | 43 ++++++++++++++++++++++
 .../src/context/openGroups/OpenGroupsProvider.tsx  |  9 ++---
 .../ui/src/context/timezone/TimezoneProvider.tsx   |  4 +-
 .../ui/src/layouts/Details/DetailsLayout.tsx       | 23 ++++++++----
 .../airflow/ui/src/layouts/Details/Graph/Graph.tsx |  5 ++-
 .../ui/src/layouts/Details/PanelButtons.tsx        |  5 ++-
 .../ui/src/layouts/Nav/UserSettingsButton.tsx      |  3 +-
 .../airflow/ui/src/pages/Dag/Calendar/Calendar.tsx |  8 +++-
 .../airflow/ui/src/pages/Dag/Overview/Overview.tsx |  3 +-
 .../src/airflow/ui/src/pages/DagsList/DagsList.tsx |  5 +--
 .../ui/src/pages/TaskInstance/Logs/Logs.tsx        |  7 ++--
 12 files changed, 89 insertions(+), 32 deletions(-)

diff --git 
a/airflow-core/src/airflow/ui/src/components/DataTable/useTableUrlState.ts 
b/airflow-core/src/airflow/ui/src/components/DataTable/useTableUrlState.ts
index 94021d04df5..a968a0c4cb4 100644
--- a/airflow-core/src/airflow/ui/src/components/DataTable/useTableUrlState.ts
+++ b/airflow-core/src/airflow/ui/src/components/DataTable/useTableUrlState.ts
@@ -20,6 +20,7 @@ import { useSearchParams } from "react-router-dom";
 import { useLocation } from "react-router-dom";
 import { useLocalStorage } from "usehooks-ts";
 
+import { tableSortKey } from "src/constants/localStorage";
 import { useConfig } from "src/queries/useConfig";
 
 import { searchParamsToState, stateToSearchParams } from "./searchParams";
@@ -30,10 +31,7 @@ export const useTableURLState = (defaultState?: 
Partial<TableState>) => {
   const location = useLocation();
   const pageName = location.pathname;
 
-  const [sorting, setSorting] = useLocalStorage<TableState["sorting"]>(
-    `${pageName.replaceAll("/", "-").slice(1)}-table-sort`,
-    [],
-  );
+  const [sorting, setSorting] = 
useLocalStorage<TableState["sorting"]>(tableSortKey(pageName), []);
 
   const pageSize = useConfig("fallback_page_limit") as number;
 
diff --git a/airflow-core/src/airflow/ui/src/constants/localStorage.ts 
b/airflow-core/src/airflow/ui/src/constants/localStorage.ts
new file mode 100644
index 00000000000..46482baddd3
--- /dev/null
+++ b/airflow-core/src/airflow/ui/src/constants/localStorage.ts
@@ -0,0 +1,43 @@
+/*!
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you 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.
+ */
+
+// Global keys
+export const TIMEZONE_KEY = "timezone";
+export const DEFAULT_DAG_VIEW_KEY = "default_dag_view";
+export const DAGS_LIST_DISPLAY_KEY = "dags_list_display";
+export const CALENDAR_GRANULARITY_KEY = "calendar-granularity";
+export const CALENDAR_VIEW_MODE_KEY = "calendar-view-mode";
+export const LOG_WRAP_KEY = "log_wrap";
+export const LOG_SHOW_TIMESTAMP_KEY = "log_show_timestamp";
+export const LOG_SHOW_SOURCE_KEY = "log_show_source";
+
+// Dag-scoped keys
+export const dagViewKey = (dagId: string) => `dag_view-${dagId}`;
+export const dagRunsLimitKey = (dagId: string) => `dag_runs_limit-${dagId}`;
+export const runTypeFilterKey = (dagId: string) => `run_type_filter-${dagId}`;
+export const triggeringUserFilterKey = (dagId: string) => 
`triggering_user_filter-${dagId}`;
+export const dagRunStateFilterKey = (dagId: string) => 
`dag_run_state_filter-${dagId}`;
+export const showGanttKey = (dagId: string) => `show_gantt-${dagId}`;
+export const dependenciesKey = (dagId: string) => `dependencies-${dagId}`;
+export const directionKey = (dagId: string) => `direction-${dagId}`;
+export const openGroupsKey = (dagId: string) => `${dagId}/open-groups`;
+export const allGroupsKey = (dagId: string) => `${dagId}/all-groups`;
+
+// Page-scoped keys
+export const tableSortKey = (pageName: string) => `${pageName.replaceAll("/", 
"-").slice(1)}-table-sort`;
diff --git 
a/airflow-core/src/airflow/ui/src/context/openGroups/OpenGroupsProvider.tsx 
b/airflow-core/src/airflow/ui/src/context/openGroups/OpenGroupsProvider.tsx
index 8ce91eb54d0..cdf9b4b8243 100644
--- a/airflow-core/src/airflow/ui/src/context/openGroups/OpenGroupsProvider.tsx
+++ b/airflow-core/src/airflow/ui/src/context/openGroups/OpenGroupsProvider.tsx
@@ -21,6 +21,7 @@ import { useDebouncedCallback } from "use-debounce";
 import { useLocalStorage } from "usehooks-ts";
 
 import { useStructureServiceStructureData } from "openapi/queries";
+import { allGroupsKey, dependenciesKey, openGroupsKey } from 
"src/constants/localStorage";
 import useSelectedVersion from "src/hooks/useSelectedVersion";
 import { flattenGraphNodes } from "src/layouts/Details/Grid/utils";
 
@@ -31,10 +32,8 @@ type Props = {
 } & PropsWithChildren;
 
 export const OpenGroupsProvider = ({ children, dagId }: Props) => {
-  const openGroupsKey = `${dagId}/open-groups`;
-  const allGroupsKey = `${dagId}/all-groups`;
-  const [openGroupIds, setOpenGroupIds] = 
useLocalStorage<Array<string>>(openGroupsKey, []);
-  const [allGroupIds, setAllGroupIds] = 
useLocalStorage<Array<string>>(allGroupsKey, []);
+  const [openGroupIds, setOpenGroupIds] = 
useLocalStorage<Array<string>>(openGroupsKey(dagId), []);
+  const [allGroupIds, setAllGroupIds] = 
useLocalStorage<Array<string>>(allGroupsKey(dagId), []);
 
   // use a ref to track the current allGroupIds without causing re-renders
   const allGroupIdsRef = useRef(allGroupIds);
@@ -45,7 +44,7 @@ export const OpenGroupsProvider = ({ children, dagId }: 
Props) => {
 
   // For Graph view support: dependencies + selected version
   const selectedVersion = useSelectedVersion();
-  const [dependencies] = useLocalStorage<"all" | "immediate" | 
"tasks">(`dependencies-${dagId}`, "tasks");
+  const [dependencies] = useLocalStorage<"all" | "immediate" | 
"tasks">(dependenciesKey(dagId), "tasks");
 
   // Fetch structure (minimal params if you want it lightweight for Grid)
   const { data: structure = { edges: [], nodes: [] } } = 
useStructureServiceStructureData(
diff --git 
a/airflow-core/src/airflow/ui/src/context/timezone/TimezoneProvider.tsx 
b/airflow-core/src/airflow/ui/src/context/timezone/TimezoneProvider.tsx
index 275b034b5c3..540868d19ff 100644
--- a/airflow-core/src/airflow/ui/src/context/timezone/TimezoneProvider.tsx
+++ b/airflow-core/src/airflow/ui/src/context/timezone/TimezoneProvider.tsx
@@ -19,9 +19,9 @@
 import type { PropsWithChildren } from "react";
 import { useLocalStorage } from "usehooks-ts";
 
-import { TimezoneContext, type TimezoneContextType } from "./Context";
+import { TIMEZONE_KEY } from "src/constants/localStorage";
 
-const TIMEZONE_KEY = "timezone";
+import { TimezoneContext, type TimezoneContextType } from "./Context";
 
 export const TimezoneProvider = ({ children }: PropsWithChildren) => {
   const systemTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
index ffc687fd984..09d116a8370 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/DetailsLayout.tsx
@@ -41,6 +41,15 @@ import { TriggerDAGButton } from 
"src/components/TriggerDag/TriggerDAGButton";
 import { ProgressBar } from "src/components/ui";
 import { Toaster } from "src/components/ui";
 import { Tooltip } from "src/components/ui/Tooltip";
+import {
+  dagRunsLimitKey,
+  dagRunStateFilterKey,
+  dagViewKey,
+  DEFAULT_DAG_VIEW_KEY,
+  runTypeFilterKey,
+  showGanttKey,
+  triggeringUserFilterKey,
+} from "src/constants/localStorage";
 import { HoverProvider } from "src/context/hover";
 import { OpenGroupsProvider } from "src/context/openGroups";
 
@@ -61,24 +70,24 @@ export const DetailsLayout = ({ children, error, isLoading, 
tabs }: Props) => {
   const { t: translate } = useTranslation();
   const { dagId = "", runId } = useParams();
   const { data: dag } = useDagServiceGetDag({ dagId });
-  const [defaultDagView] = useLocalStorage<"graph" | 
"grid">("default_dag_view", "grid");
+  const [defaultDagView] = useLocalStorage<"graph" | 
"grid">(DEFAULT_DAG_VIEW_KEY, "grid");
   const panelGroupRef = useRef<ImperativePanelGroupHandle | null>(null);
-  const [dagView, setDagView] = useLocalStorage<"graph" | 
"grid">(`dag_view-${dagId}`, defaultDagView);
-  const [limit, setLimit] = useLocalStorage<number>(`dag_runs_limit-${dagId}`, 
10);
+  const [dagView, setDagView] = useLocalStorage<"graph" | 
"grid">(dagViewKey(dagId), defaultDagView);
+  const [limit, setLimit] = useLocalStorage<number>(dagRunsLimitKey(dagId), 
10);
   const [runTypeFilter, setRunTypeFilter] = useLocalStorage<DagRunType | 
undefined>(
-    `run_type_filter-${dagId}`,
+    runTypeFilterKey(dagId),
     undefined,
   );
   const [triggeringUserFilter, setTriggeringUserFilter] = 
useLocalStorage<string | undefined>(
-    `triggering_user_filter-${dagId}`,
+    triggeringUserFilterKey(dagId),
     undefined,
   );
   const [dagRunStateFilter, setDagRunStateFilter] = 
useLocalStorage<DagRunState | undefined>(
-    `dag_run_state_filter-${dagId}`,
+    dagRunStateFilterKey(dagId),
     undefined,
   );
 
-  const [showGantt, setShowGantt] = 
useLocalStorage<boolean>(`show_gantt-${dagId}`, false);
+  const [showGantt, setShowGantt] = 
useLocalStorage<boolean>(showGanttKey(dagId), false);
   const { fitView, getZoom } = useReactFlow();
   const { data: warningData } = useDagWarningServiceListDagWarnings({ dagId });
   const { onClose, onOpen, open } = useDisclosure();
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/Graph/Graph.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/Graph/Graph.tsx
index 21593ff128b..0b69efb7d43 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/Graph/Graph.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/Graph/Graph.tsx
@@ -28,6 +28,7 @@ import { DownloadButton } from 
"src/components/Graph/DownloadButton";
 import { edgeTypes, nodeTypes } from "src/components/Graph/graphTypes";
 import type { CustomNodeProps } from "src/components/Graph/reactflowUtils";
 import { type Direction, useGraphLayout } from 
"src/components/Graph/useGraphLayout";
+import { dependenciesKey, directionKey } from "src/constants/localStorage";
 import { useColorMode } from "src/context/colorMode";
 import { useOpenGroups } from "src/context/openGroups";
 import useSelectedVersion from "src/hooks/useSelectedVersion";
@@ -85,8 +86,8 @@ export const Graph = () => {
 
   const { allGroupIds, openGroupIds, setAllGroupIds } = useOpenGroups();
 
-  const [dependencies] = useLocalStorage<"all" | "immediate" | 
"tasks">(`dependencies-${dagId}`, "tasks");
-  const [direction] = useLocalStorage<Direction>(`direction-${dagId}`, 
"RIGHT");
+  const [dependencies] = useLocalStorage<"all" | "immediate" | 
"tasks">(dependenciesKey(dagId), "tasks");
+  const [direction] = useLocalStorage<Direction>(directionKey(dagId), "RIGHT");
 
   const selectedColor = colorMode === "dark" ? selectedDarkColor : 
selectedLightColor;
   const { data: graphData = { edges: [], nodes: [] } } = 
useStructureServiceStructureData(
diff --git a/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
index 488b1b388b6..cdcaa90f3fc 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Details/PanelButtons.tsx
@@ -50,6 +50,7 @@ import { StateBadge } from "src/components/StateBadge";
 import { Tooltip } from "src/components/ui";
 import { type ButtonGroupOption, ButtonGroupToggle } from 
"src/components/ui/ButtonGroupToggle";
 import { Checkbox } from "src/components/ui/Checkbox";
+import { dependenciesKey, directionKey } from "src/constants/localStorage";
 import { dagRunTypeOptions, dagRunStateOptions } from 
"src/constants/stateOptions";
 import { useContainerWidth } from "src/utils/useContainerWidth";
 
@@ -126,10 +127,10 @@ export const PanelButtons = ({
   const { fitView } = useReactFlow();
   const shouldShowToggleButtons = Boolean(runId);
   const [dependencies, setDependencies, removeDependencies] = 
useLocalStorage<Dependency>(
-    `dependencies-${dagId}`,
+    dependenciesKey(dagId),
     "tasks",
   );
-  const [direction, setDirection] = 
useLocalStorage<Direction>(`direction-${dagId}`, "RIGHT");
+  const [direction, setDirection] = 
useLocalStorage<Direction>(directionKey(dagId), "RIGHT");
   const containerRef = useRef<HTMLDivElement>(null);
   const containerWidth = useContainerWidth(containerRef);
   const handleLimitChange = (event: SelectValueChangeDetails<{ label: string; 
value: Array<string> }>) => {
diff --git a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx 
b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx
index 02bf017f6eb..2ad032457e7 100644
--- a/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx
+++ b/airflow-core/src/airflow/ui/src/layouts/Nav/UserSettingsButton.tsx
@@ -35,6 +35,7 @@ import { useLocalStorage } from "usehooks-ts";
 
 import { useAuthLinksServiceGetCurrentUserInfo } from "openapi/queries";
 import { Menu } from "src/components/ui";
+import { DEFAULT_DAG_VIEW_KEY } from "src/constants/localStorage";
 import { useColorMode } from "src/context/colorMode/useColorMode";
 import type { NavItemResponse } from "src/utils/types";
 
@@ -77,7 +78,7 @@ export const UserSettingsButton = ({ externalViews }: { 
readonly externalViews:
   const { onClose: onCloseLogout, onOpen: onOpenLogout, open: isOpenLogout } = 
useDisclosure();
   const { onClose: onCloseLanguage, onOpen: onOpenLanguage, open: 
isOpenLanguage } = useDisclosure();
 
-  const [dagView, setDagView] = useLocalStorage<"graph" | 
"grid">("default_dag_view", "grid");
+  const [dagView, setDagView] = useLocalStorage<"graph" | 
"grid">(DEFAULT_DAG_VIEW_KEY, "grid");
 
   const theme = selectedTheme ?? COLOR_MODES.SYSTEM;
 
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Calendar/Calendar.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Calendar/Calendar.tsx
index faa7b0956ba..41ac7beaba3 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Calendar/Calendar.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Calendar/Calendar.tsx
@@ -28,6 +28,7 @@ import { useLocalStorage } from "usehooks-ts";
 import { useCalendarServiceGetCalendar } from "openapi/queries";
 import { ErrorAlert } from "src/components/ErrorAlert";
 import { ButtonGroupToggle } from "src/components/ui/ButtonGroupToggle";
+import { CALENDAR_GRANULARITY_KEY, CALENDAR_VIEW_MODE_KEY } from 
"src/constants/localStorage";
 
 import { CalendarLegend } from "./CalendarLegend";
 import { DailyCalendarView } from "./DailyCalendarView";
@@ -43,8 +44,11 @@ export const Calendar = () => {
   const { dagId = "" } = useParams();
   const { t: translate } = useTranslation("dag");
   const [selectedDate, setSelectedDate] = useState(dayjs());
-  const [granularity, setGranularity] = useLocalStorage<"daily" | 
"hourly">("calendar-granularity", "hourly");
-  const [viewMode, setViewMode] = useLocalStorage<"failed" | 
"total">("calendar-view-mode", "total");
+  const [granularity, setGranularity] = useLocalStorage<"daily" | "hourly">(
+    CALENDAR_GRANULARITY_KEY,
+    "hourly",
+  );
+  const [viewMode, setViewMode] = useLocalStorage<"failed" | 
"total">(CALENDAR_VIEW_MODE_KEY, "total");
 
   const currentDate = dayjs();
 
diff --git a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx 
b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
index 8cebcc4ba0b..043ae4d1b15 100644
--- a/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/Dag/Overview/Overview.tsx
@@ -33,6 +33,7 @@ import { DurationChart } from "src/components/DurationChart";
 import { NeedsReviewButton } from "src/components/NeedsReviewButton";
 import TimeRangeSelector from "src/components/TimeRangeSelector";
 import { TrendCountButton } from "src/components/TrendCountButton";
+import { dagRunsLimitKey } from "src/constants/localStorage";
 import { SearchParamsKeys } from "src/constants/searchParams";
 import { useGridRuns } from "src/queries/useGridRuns.ts";
 
@@ -58,7 +59,7 @@ export const Overview = () => {
     state: ["failed"],
   });
 
-  const [limit] = useLocalStorage<number>(`dag_runs_limit-${dagId}`, 10);
+  const [limit] = useLocalStorage<number>(dagRunsLimitKey(dagId ?? ""), 10);
   const { data: failedRuns, isLoading: isLoadingFailedRuns } = 
useDagRunServiceGetDagRuns({
     dagId: dagId ?? "",
     limit,
diff --git a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx 
b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
index 02c16c15530..92b6a4865e2 100644
--- a/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/DagsList/DagsList.tsx
@@ -44,6 +44,7 @@ import { NeedsReviewBadge } from 
"src/components/NeedsReviewBadge";
 import { SearchBar } from "src/components/SearchBar";
 import { TogglePause } from "src/components/TogglePause";
 import { TriggerDAGButton } from "src/components/TriggerDag/TriggerDAGButton";
+import { DAGS_LIST_DISPLAY_KEY } from "src/constants/localStorage";
 import { SearchParamsKeys, type SearchParamsKeysType } from 
"src/constants/searchParams";
 import { DagsLayout } from "src/layouts/DagsLayout";
 import { useConfig } from "src/queries/useConfig";
@@ -199,12 +200,10 @@ const cardDef: CardDef<DAGWithLatestDagRunsResponse> = {
   },
 };
 
-const DAGS_LIST_DISPLAY = "dags_list_display";
-
 export const DagsList = () => {
   const { t: translate } = useTranslation();
   const [searchParams, setSearchParams] = useSearchParams();
-  const [display, setDisplay] = useLocalStorage<"card" | 
"table">(DAGS_LIST_DISPLAY, "card");
+  const [display, setDisplay] = useLocalStorage<"card" | 
"table">(DAGS_LIST_DISPLAY_KEY, "card");
   const dagRunsLimit = display === "card" ? 14 : 1;
 
   const hidePausedDagsByDefault = 
Boolean(useConfig("hide_paused_dags_by_default"));
diff --git a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx 
b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx
index 37df6135463..d5fd32a8306 100644
--- a/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx
+++ b/airflow-core/src/airflow/ui/src/pages/TaskInstance/Logs/Logs.tsx
@@ -26,6 +26,7 @@ import { useLocalStorage } from "usehooks-ts";
 import { useTaskInstanceServiceGetMappedTaskInstance } from "openapi/queries";
 import { renderStructuredLog } from "src/components/renderStructuredLog";
 import { Dialog } from "src/components/ui";
+import { LOG_SHOW_SOURCE_KEY, LOG_SHOW_TIMESTAMP_KEY, LOG_WRAP_KEY } from 
"src/constants/localStorage";
 import { SearchParamsKeys } from "src/constants/searchParams";
 import { useConfig } from "src/queries/useConfig";
 import { useLogs } from "src/queries/useLogs";
@@ -75,9 +76,9 @@ export const Logs = () => {
 
   const defaultWrap = Boolean(useConfig("default_wrap"));
 
-  const [wrap, setWrap] = useLocalStorage<boolean>("log_wrap", defaultWrap);
-  const [showTimestamp, setShowTimestamp] = 
useLocalStorage<boolean>("log_show_timestamp", true);
-  const [showSource, setShowSource] = 
useLocalStorage<boolean>("log_show_source", false);
+  const [wrap, setWrap] = useLocalStorage<boolean>(LOG_WRAP_KEY, defaultWrap);
+  const [showTimestamp, setShowTimestamp] = 
useLocalStorage<boolean>(LOG_SHOW_TIMESTAMP_KEY, true);
+  const [showSource, setShowSource] = 
useLocalStorage<boolean>(LOG_SHOW_SOURCE_KEY, false);
   const [fullscreen, setFullscreen] = useState(false);
   const [expanded, setExpanded] = useState(false);
 

Reply via email to