Skip to content

Commit fcc6bfb

Browse files
Keep open tabs up-to-date using broadcast channel
1 parent 4ff7d06 commit fcc6bfb

File tree

7 files changed

+68
-53
lines changed

7 files changed

+68
-53
lines changed

src/components/ActionNameCard.tsx

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ import {
1111
Input,
1212
useToast,
1313
} from "@chakra-ui/react";
14-
import { useCallback, useMemo, useState } from "react";
14+
import { useCallback, useEffect, useMemo, useState } from "react";
1515
import { useIntl } from "react-intl";
1616
import { Action } from "../model";
1717
import { useStore } from "../store";
@@ -57,6 +57,10 @@ const ActionNameCard = ({
5757
const setActionIcon = useStore((s) => s.setActionIcon);
5858
const { icon, id } = value;
5959
const [localName, setLocalName] = useState<string>(value.name);
60+
useEffect(() => {
61+
// Occurs when the name is updated in another tab.
62+
setLocalName(value.name);
63+
}, [value.name]);
6064
const predictionResult = useStore((s) => s.predictionResult);
6165
const isTriggered =
6266
viewMode === ActionCardNameViewMode.ReadOnly

src/components/DataSamplesTableRow.tsx

Lines changed: 41 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -41,51 +41,49 @@ const DataSamplesTableRow = ({
4141
const intl = useIntl();
4242

4343
return (
44-
<>
45-
<Box
46-
ref={selected ? renameShortcutScopeRef : undefined}
47-
role="region"
48-
aria-label={intl.formatMessage(
49-
{
50-
id: "action-region",
51-
},
52-
{ action: action.name }
53-
)}
54-
display="contents"
55-
onFocusCapture={onSelectRow}
56-
>
44+
<Box
45+
ref={selected ? renameShortcutScopeRef : undefined}
46+
role="region"
47+
aria-label={intl.formatMessage(
48+
{
49+
id: "action-region",
50+
},
51+
{ action: action.name }
52+
)}
53+
display="contents"
54+
onFocusCapture={onSelectRow}
55+
>
56+
<GridItem>
57+
<ActionNameCard
58+
value={action}
59+
onDeleteAction={onDeleteAction}
60+
onSelectRow={onSelectRow}
61+
selected={selected}
62+
viewMode={
63+
preview
64+
? ActionCardNameViewMode.Preview
65+
: ActionCardNameViewMode.Editable
66+
}
67+
/>
68+
</GridItem>
69+
{showHints ? (
70+
<DataSamplesTableHints action={action} onRecord={onRecord} />
71+
) : (
5772
<GridItem>
58-
<ActionNameCard
59-
value={action}
60-
onDeleteAction={onDeleteAction}
61-
onSelectRow={onSelectRow}
62-
selected={selected}
63-
viewMode={
64-
preview
65-
? ActionCardNameViewMode.Preview
66-
: ActionCardNameViewMode.Editable
67-
}
68-
/>
73+
{(action.name.length > 0 || action.recordings.length > 0) && (
74+
<ActionDataSamplesCard
75+
preview={preview}
76+
newRecordingId={newRecordingId}
77+
value={action}
78+
selected={selected}
79+
onSelectRow={onSelectRow}
80+
onRecord={onRecord}
81+
clearNewRecordingId={clearNewRecordingId}
82+
/>
83+
)}
6984
</GridItem>
70-
{showHints ? (
71-
<DataSamplesTableHints action={action} onRecord={onRecord} />
72-
) : (
73-
<GridItem>
74-
{(action.name.length > 0 || action.recordings.length > 0) && (
75-
<ActionDataSamplesCard
76-
preview={preview}
77-
newRecordingId={newRecordingId}
78-
value={action}
79-
selected={selected}
80-
onSelectRow={onSelectRow}
81-
onRecord={onRecord}
82-
clearNewRecordingId={clearNewRecordingId}
83-
/>
84-
)}
85-
</GridItem>
86-
)}
87-
</Box>
88-
</>
85+
)}
86+
</Box>
8987
);
9088
};
9189

src/components/LiveGraphLabels.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ const LiveGraphLabels = () => {
8484

8585
return (
8686
<Box w={10} h={40} position="relative">
87-
{labelConfig.map((config, idx) => (
88-
<React.Fragment key={idx}>
87+
{labelConfig.map((config) => (
88+
<React.Fragment key={config.label}>
8989
<Box
9090
ref={config.arrowHeightRef}
9191
ml={-7}

src/components/RecordingFingerprint.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,10 +37,10 @@ const RecordingFingerprint = ({
3737
templateColumns={`repeat(${Object.keys(dataFeatures).length}, 1fr)`}
3838
{...rest}
3939
>
40-
{Object.keys(dataFeatures).map((k, idx) => (
40+
{Object.keys(dataFeatures).map((k) => (
4141
<ClickableTooltip
4242
placement="end-end"
43-
key={idx}
43+
key={k}
4444
label={
4545
<Text p={3}>
4646
<FormattedMessage id={`fingerprint-${k}-tooltip`} />

src/components/TestingModelTable.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,11 +83,11 @@ const TestingModelTable = () => {
8383
h="fit-content"
8484
alignSelf="start"
8585
>
86-
{actions.map((action, idx) => {
86+
{actions.map((action) => {
8787
const { requiredConfidence: threshold } = action;
8888
return (
8989
<Box
90-
key={idx}
90+
key={action.id}
9191
role="region"
9292
aria-label={intl.formatMessage(
9393
{

src/storage.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ interface MakeCodeData {
2424
projectEdited: boolean;
2525
}
2626

27-
export enum DatabaseStore {
27+
enum DatabaseStore {
2828
PROJECT_DATA = "project-data",
2929
MAKECODE = "makecode-project",
3030
RECORDINGS = "recordings",

src/store.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,11 @@ import { getTotalNumSamples } from "./utils/actions";
5656
import { defaultIcons, MakeCodeIcon } from "./utils/icons";
5757
import { getDetectedAction } from "./utils/prediction";
5858

59+
export enum BroadcastChannelMessages {
60+
RELOAD_PROJECT = "reload-project",
61+
}
62+
const broadcastChannel = new BroadcastChannel("ml");
63+
5964
const storage = new Database();
6065

6166
export const modelUrl = "indexeddb://micro:bit-ai-creator-model";
@@ -1541,9 +1546,11 @@ const storageWithErrHandling = async <T>(
15411546
) => {
15421547
try {
15431548
if (Array.isArray(callback)) {
1544-
return await Promise.all(callback);
1549+
await Promise.all(callback);
1550+
} else {
1551+
await callback();
15451552
}
1546-
return await callback();
1553+
broadcastChannel.postMessage(BroadcastChannelMessages.RELOAD_PROJECT);
15471554
} catch (err) {
15481555
if (err instanceof DOMException && err.name === "QuotaExceededError") {
15491556
console.error("Storage quota exceeded!", err);
@@ -1559,3 +1566,9 @@ export const loadProjectFromStorage = async () => {
15591566
await loadProjectFromStorage();
15601567
return true;
15611568
};
1569+
1570+
broadcastChannel.onmessage = async (event) => {
1571+
if (event.data === BroadcastChannelMessages.RELOAD_PROJECT) {
1572+
await loadProjectFromStorage();
1573+
}
1574+
};

0 commit comments

Comments
 (0)