Skip to content

Commit 6b1ea5e

Browse files
authored
refactor: move selected page into awareness state (#4371)
Ref #4364 We need to implement universal linking of current user view. For this I added "awareness" state which reflects terminology from collaboration libraries. First migrated selected page id and fixed usages.
1 parent 4cd51fa commit 6b1ea5e

36 files changed

+84
-75
lines changed

apps/builder/app/builder/features/address-bar.stories.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,9 @@ import {
77
$dataSourceVariables,
88
$dataSources,
99
$pages,
10-
$selectedPage,
11-
$selectedPageId,
1210
} from "~/shared/nano-states";
1311
import { registerContainers } from "~/shared/sync";
12+
import { $awareness, $selectedPage } from "~/shared/awareness";
1413

1514
registerContainers();
1615

@@ -98,7 +97,7 @@ export default {
9897
} satisfies Meta;
9998

10099
export const AddressBar: StoryFn = () => {
101-
$selectedPageId.set("dynamicId");
100+
$awareness.set({ pageId: "dynamicId" });
102101
return (
103102
<>
104103
<Box

apps/builder/app/builder/features/address-bar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ import {
3737
$dataSourceVariables,
3838
$pages,
3939
$publishedOrigin,
40-
$selectedPage,
4140
$selectedPageDefaultSystem,
4241
updateSystem,
4342
} from "~/shared/nano-states";
@@ -48,6 +47,7 @@ import {
4847
tokenizePathnamePattern,
4948
} from "~/builder/shared/url-pattern";
5049
import { savePathInHistory } from "~/shared/pages";
50+
import { $selectedPage } from "~/shared/awareness";
5151

5252
const $selectedPagePath = computed([$selectedPage, $pages], (page, pages) => {
5353
if (pages === undefined || page === undefined) {

apps/builder/app/builder/features/ai/ai-command-bar.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@ import { useRef, useState, type ComponentPropsWithoutRef } from "react";
3030
import {
3131
$collaborativeInstanceSelector,
3232
$selectedInstanceSelector,
33-
$selectedPage,
3433
} from "~/shared/nano-states";
3534
import { useMediaRecorder } from "./hooks/media-recorder";
3635
import { useLongPressToggle } from "./hooks/long-press-toggle";
@@ -41,6 +40,7 @@ import { useEffectEvent } from "~/shared/hook-utils/effect-event";
4140
import { AiApiException, RateLimitException } from "./api-exceptions";
4241
import { getSetting, setSetting } from "~/builder/shared/client-settings";
4342
import { flushSync } from "react-dom";
43+
import { $selectedPage } from "~/shared/awareness";
4444

4545
type PartialButtonProps<T = ComponentPropsWithoutRef<typeof Button>> = {
4646
[key in keyof T]?: T[key];

apps/builder/app/builder/features/components/components.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import {
2626
import { CollapsibleSection } from "~/builder/shared/collapsible-section";
2727
import { dragItemAttribute, useDraggable } from "./use-draggable";
2828
import { MetaIcon } from "~/builder/shared/meta-icon";
29-
import { $registeredComponentMetas, $selectedPage } from "~/shared/nano-states";
29+
import { $registeredComponentMetas } from "~/shared/nano-states";
3030
import {
3131
getMetaMaps,
3232
type MetaByCategory,
@@ -38,6 +38,7 @@ import { insert } from "./insert";
3838
import { matchSorter } from "match-sorter";
3939
import { parseComponentName } from "@webstudio-is/sdk";
4040
import type { Publish } from "~/shared/pubsub";
41+
import { $selectedPage } from "~/shared/awareness";
4142

4243
const matchComponents = (
4344
metas: Array<WsComponentMeta>,

apps/builder/app/builder/features/components/insert.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@ import {
55
$instances,
66
$registeredComponentMetas,
77
$selectedInstanceSelector,
8-
$selectedPage,
98
} from "~/shared/nano-states";
109
import {
1110
computeInstancesConstraints,
1211
findClosestDroppableTarget,
1312
getComponentTemplateData,
1413
insertTemplateData,
1514
} from "~/shared/instance-utils";
15+
import { $selectedPage } from "~/shared/awareness";
1616

1717
const formatInsertionError = (component: string, meta: WsComponentMeta) => {
1818
const or = new Intl.ListFormat("en", {

apps/builder/app/builder/features/inspector/inspector.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,14 @@ import {
2525
$selectedInstance,
2626
$registeredComponentMetas,
2727
$dragAndDropState,
28-
$selectedPage,
2928
} from "~/shared/nano-states";
3029
import { NavigatorTree } from "~/builder/features/navigator";
3130
import type { Settings } from "~/builder/shared/client-settings";
3231
import { MetaIcon } from "~/builder/shared/meta-icon";
3332
import { getInstanceLabel } from "~/shared/instance-utils";
3433
import { BindingPopoverProvider } from "~/builder/shared/binding-popover";
3534
import { $activeInspectorPanel } from "~/builder/shared/nano-states";
35+
import { $selectedPage } from "~/shared/awareness";
3636

3737
const InstanceInfo = ({ instance }: { instance: Instance }) => {
3838
const metas = useStore($registeredComponentMetas);

apps/builder/app/builder/features/navigator/navigator-tree.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import {
4141
$propValuesByInstanceSelector,
4242
$registeredComponentMetas,
4343
$selectedInstanceSelector,
44-
$selectedPage,
4544
getIndexedInstanceId,
4645
type ItemDropTarget,
4746
} from "~/shared/nano-states";
@@ -56,6 +55,7 @@ import {
5655
} from "~/shared/instance-utils";
5756
import { emitCommand } from "~/builder/shared/commands";
5857
import { useContentEditable } from "~/shared/dom-hooks";
58+
import { $selectedPage } from "~/shared/awareness";
5959

6060
type TreeItem = {
6161
level: number;

apps/builder/app/builder/features/pages/page-utils.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ import {
2323
$dataSources,
2424
$pages,
2525
$resourceValues,
26-
$selectedPageId,
2726
} from "~/shared/nano-states";
2827
import { registerContainers } from "~/shared/sync";
28+
import { $awareness } from "~/shared/awareness";
2929

3030
setEnv("*");
3131
registerContainers();
@@ -413,7 +413,7 @@ test("page root scope should rely on selected page", () => {
413413
systemDataSourceId: "system",
414414
});
415415
$pages.set(pages);
416-
$selectedPageId.set("pageId");
416+
$awareness.set({ pageId: "pageId" });
417417
$dataSources.set(
418418
toMap([
419419
{
@@ -447,7 +447,7 @@ test("page root scope should use variable and resource values", () => {
447447
systemDataSourceId: "system",
448448
})
449449
);
450-
$selectedPageId.set("homePageId");
450+
$awareness.set({ pageId: "homePageId" });
451451
$dataSources.set(
452452
toMap([
453453
{
@@ -494,7 +494,7 @@ test("page root scope should prefill default system variable value", () => {
494494
systemDataSourceId: "systemId",
495495
})
496496
);
497-
$selectedPageId.set("homePageId");
497+
$awareness.set({ pageId: "homePageId" });
498498
$dataSources.set(
499499
toMap([
500500
{

apps/builder/app/builder/features/pages/page-utils.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,10 @@ import {
2121
$dataSources,
2222
$pages,
2323
$selectedInstanceSelector,
24-
$selectedPage,
25-
$selectedPageId,
2624
$variableValuesByInstanceSelector,
2725
} from "~/shared/nano-states";
2826
import { insertPageCopyMutable } from "~/shared/page-utils";
27+
import { $awareness, $selectedPage } from "~/shared/awareness";
2928

3029
/**
3130
* When page or folder needs to be deleted or moved to a different parent,
@@ -206,8 +205,8 @@ export const getAllChildrenAndSelf = (
206205
export const deletePageMutable = (pageId: Page["id"], data: WebstudioData) => {
207206
const { pages } = data;
208207
// deselect page before deleting to avoid flash of content
209-
if ($selectedPageId.get() === pageId) {
210-
$selectedPageId.set(pages.homePage.id);
208+
if ($awareness.get()?.pageId === pageId) {
209+
$awareness.set({ pageId: pages.homePage.id });
211210
$selectedInstanceSelector.set(undefined);
212211
}
213212
const rootInstanceId = findPageByIdOrPath(pageId, pages)?.rootInstanceId;

apps/builder/app/builder/features/pages/pages.tsx

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ import {
2727
} from "@webstudio-is/icons";
2828
import { ExtendedPanel } from "../../shared/extended-sidebar-panel";
2929
import { NewPageSettings, PageSettings } from "./page-settings";
30-
import { $editingPageId, $pages, $selectedPageId } from "~/shared/nano-states";
30+
import { $editingPageId, $pages } from "~/shared/nano-states";
3131
import { switchPage } from "~/shared/pages";
3232
import {
3333
getAllChildrenAndSelf,
@@ -50,6 +50,7 @@ import {
5050
import { atom, computed } from "nanostores";
5151
import { isPathnamePattern } from "~/builder/shared/url-pattern";
5252
import { updateWebstudioData } from "~/shared/instance-utils";
53+
import { $selectedPage } from "~/shared/awareness";
5354

5455
const ItemSuffix = ({
5556
isParentSelected,
@@ -439,7 +440,7 @@ const PageEditor = ({
439440
editingPageId: string;
440441
onClose: () => void;
441442
}) => {
442-
const currentPageId = useStore($selectedPageId);
443+
const currentPage = useStore($selectedPage);
443444

444445
if (editingPageId === newPageId) {
445446
return (
@@ -459,7 +460,7 @@ const PageEditor = ({
459460
onDelete={() => {
460461
onClose();
461462
// switch to home page when deleted currently selected page
462-
if (editingPageId === currentPageId) {
463+
if (editingPageId === currentPage?.id) {
463464
const pages = $pages.get();
464465
if (pages) {
465466
switchPage(pages.homePage.id);
@@ -504,11 +505,11 @@ const FolderEditor = ({
504505
};
505506

506507
export const PagesPanel = ({ onClose }: { onClose: () => void }) => {
507-
const currentPageId = useStore($selectedPageId);
508+
const currentPage = useStore($selectedPage);
508509
const editingItemId = useStore($editingPageId);
509510
const pages = useStore($pages);
510511

511-
if (currentPageId === undefined || pages === undefined) {
512+
if (currentPage === undefined || pages === undefined) {
512513
return;
513514
}
514515

@@ -557,7 +558,7 @@ export const PagesPanel = ({ onClose }: { onClose: () => void }) => {
557558
<Separator />
558559

559560
<PagesTree
560-
selectedPageId={currentPageId}
561+
selectedPageId={currentPage.id}
561562
onSelect={(itemId) => {
562563
switchPage(itemId);
563564
onClose();
@@ -566,7 +567,7 @@ export const PagesPanel = ({ onClose }: { onClose: () => void }) => {
566567
onEdit={(itemId) => {
567568
// always select page when edit its settings
568569
if (itemId && isFolder(itemId, pages.folders) === false) {
569-
$selectedPageId.set(itemId);
570+
switchPage(itemId);
570571
}
571572
$editingPageId.set(itemId);
572573
}}

0 commit comments

Comments
 (0)