Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,20 @@
"icon": "$(refresh)",
"category": "Bevy Inspector"
},
{
"command": "bevyInspector.expandAllComponents",
"title": "Expand",
"icon": "$(expand-all)",
"category": "Bevy Inspector",
"enablement": "view == bevyInspector.components"
},
{
"command": "bevyInspector.collapseAllComponents",
"title": "Collapse",
"icon": "$(collapse-all)",
"category": "Bevy Inspector",
"enablement": "view == bevyInspector.components"
},
{
"command": "bevyInspector.enableComponentsPolling",
"title": "Enable Polling Components",
Expand All @@ -154,6 +168,20 @@
"category": "Bevy Inspector",
"enablement": "view == bevyInspector.resources"
},
{
"command": "bevyInspector.expandAllResources",
"title": "Expand",
"icon": "$(expand-all)",
"category": "Bevy Inspector",
"enablement": "view == bevyInspector.resources"
},
{
"command": "bevyInspector.collapseAllResources",
"title": "Collapse",
"icon": "$(collapse-all)",
"category": "Bevy Inspector",
"enablement": "view == bevyInspector.resources"
},
{
"command": "bevyInspector.enableResourcesPolling",
"title": "Enable Polling Resources",
Expand Down Expand Up @@ -250,6 +278,16 @@
"when": "view == bevyInspector.components",
"group": "navigation"
},
{
"command": "bevyInspector.expandAllComponents",
"when": "view == bevyInspector.components && !bevyInspector.anyComponentExpanded",
"group": "navigation@99"
},
{
"command": "bevyInspector.collapseAllComponents",
"when": "view == bevyInspector.components && bevyInspector.anyComponentExpanded",
"group": "navigation@99"
},
{
"command": "bevyInspector.enableComponentsPolling",
"when": "view == bevyInspector.components && !bevyInspector.componentsPollingEnabled",
Expand All @@ -265,6 +303,16 @@
"when": "view == bevyInspector.resources",
"group": "navigation"
},
{
"command": "bevyInspector.expandAllResources",
"when": "view == bevyInspector.resources && !bevyInspector.anyResourceExpanded",
"group": "navigation@99"
},
{
"command": "bevyInspector.collapseAllResources",
"when": "view == bevyInspector.resources && bevyInspector.anyResourceExpanded",
"group": "navigation@99"
},
{
"command": "bevyInspector.enableResourcesPolling",
"when": "view == bevyInspector.resources && !bevyInspector.resourcesPollingEnabled",
Expand Down
7 changes: 4 additions & 3 deletions src/components-view/components/ComponentsView.tsx
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { ValuesUpdatedData } from '../../inspector-data/messages';
import { ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import type { CollapsibleStateData, ValuesUpdatedData } from '../../inspector-data/messages';
import { SetCollapsibleState, ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import { usePublisher } from '../../messenger/usePublisher';
import { useSubscriber } from '../../messenger/useSubscriber';
import { EmptyDetails } from './EmptyDetails';
import { TypedValueDetails } from '../../schema-components/TypedValueDetails';

export function ComponentsView() {
const components = useSubscriber<ValuesUpdatedData>(ValuesUpdated);
const collapsibleState = useSubscriber<CollapsibleStateData>(SetCollapsibleState);
usePublisher(ViewReady, null);

if (!components) {
Expand All @@ -15,7 +16,7 @@ export function ComponentsView() {
return (
<>
{components.map((component) => (
<TypedValueDetails key={component.schema.typePath} typedValue={component} />
<TypedValueDetails key={component.schema.typePath} typedValue={component} collapsibleState={collapsibleState} />
))}
</>
);
Expand Down
30 changes: 29 additions & 1 deletion src/extension/components/componentsController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import * as vscode from 'vscode';
import type { UpdateRequestedEvent, ValuesUpdatedEvent, ViewEvent } from '../../inspector-data/messages';
import { UpdateRequested, ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import {
CollapsibleStateChanged,
SetCollapsibleState,
UpdateRequested,
ValuesUpdated,
ViewReady,
} from '../../inspector-data/messages';
import type { TypePath } from '../../inspector-data/types';
import { isEventMessage } from '../../inspector-data/types';
import type { EntityNode } from '../entities/entityTree';
Expand Down Expand Up @@ -31,6 +37,8 @@ export class ComponentsController implements vscode.Disposable {
vscode.commands.registerCommand('bevyInspector.refreshComponents', this.refresh.bind(this)),
vscode.commands.registerCommand('bevyInspector.enableComponentsPolling', this.enablePolling.bind(this)),
vscode.commands.registerCommand('bevyInspector.disableComponentsPolling', this.disablePolling.bind(this)),
vscode.commands.registerCommand('bevyInspector.expandAllComponents', this.expandAll.bind(this)),
vscode.commands.registerCommand('bevyInspector.collapseAllComponents', this.collapseAll.bind(this)),
);
this.pollingService.onRefresh(this.refresh.bind(this));
vscode.workspace.onDidChangeConfiguration((e) => {
Expand All @@ -42,6 +50,8 @@ export class ComponentsController implements vscode.Disposable {
// Enable polling by default.
this.enablePolling();

vscode.commands.executeCommand('setContext', 'bevyInspector.anyComponentExpanded', false);

this.componentsViewProvider.onVisibilityChanged((visible) => {
if (visible) {
this.enablePolling();
Expand Down Expand Up @@ -127,6 +137,10 @@ export class ComponentsController implements vscode.Disposable {
case ViewReady: {
break;
}
case CollapsibleStateChanged: {
vscode.commands.executeCommand('setContext', 'bevyInspector.anyComponentExpanded', event.data.anyExpanded);
break;
}
case UpdateRequested: {
const updated = await this.setComponentValue(event);
if (updated) {
Expand All @@ -139,6 +153,20 @@ export class ComponentsController implements vscode.Disposable {
}
}

private expandAll(): void {
this.componentsViewProvider.postMessage({
type: SetCollapsibleState,
data: { anyExpanded: true },
});
}

private collapseAll(): void {
this.componentsViewProvider.postMessage({
type: SetCollapsibleState,
data: { anyExpanded: false },
});
}

private async setComponentValue(event: UpdateRequestedEvent): Promise<boolean> {
try {
if (this.selectedEntity === undefined) {
Expand Down
30 changes: 29 additions & 1 deletion src/extension/resources/resourcesController.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
import * as vscode from 'vscode';
import type { UpdateRequestedEvent, ValuesUpdatedEvent, ViewEvent } from '../../inspector-data/messages';
import { UpdateRequested, ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import {
CollapsibleStateChanged,
SetCollapsibleState,
UpdateRequested,
ValuesUpdated,
ViewReady,
} from '../../inspector-data/messages';
import type { TypePath } from '../../inspector-data/types';
import { isEventMessage } from '../../inspector-data/types';
import { logger } from '../vscode/logger';
Expand All @@ -24,6 +30,8 @@ export class ResourcesController implements vscode.Disposable {
vscode.commands.registerCommand('bevyInspector.refreshResources', this.refresh.bind(this)),
vscode.commands.registerCommand('bevyInspector.enableResourcesPolling', this.enablePolling.bind(this)),
vscode.commands.registerCommand('bevyInspector.disableResourcesPolling', this.disablePolling.bind(this)),
vscode.commands.registerCommand('bevyInspector.expandAllResources', this.expandAll.bind(this)),
vscode.commands.registerCommand('bevyInspector.collapseAllResources', this.collapseAll.bind(this)),
);
this.pollingService.onRefresh(this.refresh.bind(this));
vscode.workspace.onDidChangeConfiguration((e) => {
Expand All @@ -36,6 +44,8 @@ export class ResourcesController implements vscode.Disposable {
context.subscriptions.push(
vscode.commands.registerCommand('bevyInspector.insertResource', this.insertResource.bind(this)),
);

vscode.commands.executeCommand('setContext', 'bevyInspector.anyResourceExpanded', false);
}

dispose() {
Expand Down Expand Up @@ -69,6 +79,10 @@ export class ResourcesController implements vscode.Disposable {
await this.refresh();
break;
}
case CollapsibleStateChanged: {
vscode.commands.executeCommand('setContext', 'bevyInspector.anyResourceExpanded', event.data.anyExpanded);
break;
}
case UpdateRequested: {
const updated = await this.setResourceValue(event);
if (updated) {
Expand All @@ -81,6 +95,20 @@ export class ResourcesController implements vscode.Disposable {
}
}

private expandAll(): void {
this.resourcesViewProvider.postMessage({
type: SetCollapsibleState,
data: { anyExpanded: true },
});
}

private collapseAll(): void {
this.resourcesViewProvider.postMessage({
type: SetCollapsibleState,
data: { anyExpanded: false },
});
}

private async setResourceValue(event: UpdateRequestedEvent): Promise<boolean> {
try {
await this.repository.setResourceValue(event.data.typePath, event.data.path, event.data.newValue);
Expand Down
15 changes: 13 additions & 2 deletions src/inspector-data/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,35 @@ import type { EventMessage, TypedValue, TypePath } from './types';
// Events passing from the views to the extension.
export const ViewReady = 'ViewReady';
export const UpdateRequested = 'UpdateRequested';
export const CollapsibleStateChanged = 'CollapsibleStateChanged';
export type ViewReadyData = null;
export interface UpdateRequestedData {
typePath: TypePath;
path: string;
newValue: unknown;
}
export interface CollapsibleStateData {
anyExpanded: boolean;
}
export type ViewReadyEvent = EventMessage<ViewReadyData> & {
type: typeof ViewReady;
};
export type UpdateRequestedEvent = EventMessage<UpdateRequestedData> & {
type: typeof UpdateRequested;
};
export type ViewEvent = ViewReadyEvent | UpdateRequestedEvent;
export type CollapsibleStateChangedEvent = EventMessage<CollapsibleStateData> & {
type: typeof CollapsibleStateChanged;
};
export type ViewEvent = ViewReadyEvent | UpdateRequestedEvent | CollapsibleStateChangedEvent;

// Events passing from the extension to the views.
export const ValuesUpdated = 'ValuesUpdated';
export const SetCollapsibleState = 'SetCollapsibleState';
export type ValuesUpdatedData = TypedValue[];
export type ValuesUpdatedEvent = EventMessage<ValuesUpdatedData> & {
type: typeof ValuesUpdated;
};
export type ExtensionEvent = ValuesUpdatedEvent;
export type SetCollapsibleStateEvent = EventMessage<CollapsibleStateData> & {
type: typeof SetCollapsibleState;
};
export type ExtensionEvent = ValuesUpdatedEvent | SetCollapsibleStateEvent;
7 changes: 4 additions & 3 deletions src/resources-view/components/ResourcesView.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
import type { ValuesUpdatedData } from '../../inspector-data/messages';
import { ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import type { CollapsibleStateData, ValuesUpdatedData } from '../../inspector-data/messages';
import { SetCollapsibleState, ValuesUpdated, ViewReady } from '../../inspector-data/messages';
import { usePublisher } from '../../messenger/usePublisher';
import { useSubscriber } from '../../messenger/useSubscriber';
import { TypedValueDetails } from '../../schema-components/TypedValueDetails';

export function ResourcesView() {
const resources = useSubscriber<ValuesUpdatedData>(ValuesUpdated);
const collapsibleState = useSubscriber<CollapsibleStateData>(SetCollapsibleState);
usePublisher(ViewReady, null);

if (!resources) {
Expand All @@ -14,7 +15,7 @@ export function ResourcesView() {
return (
<>
{resources.map((resource) => (
<TypedValueDetails key={resource.schema.typePath} typedValue={resource} />
<TypedValueDetails key={resource.schema.typePath} typedValue={resource} collapsibleState={collapsibleState} />
))}
</>
);
Expand Down
41 changes: 37 additions & 4 deletions src/schema-components/TypedValueDetails.tsx
Original file line number Diff line number Diff line change
@@ -1,21 +1,49 @@
import '@vscode-elements/elements/dist/vscode-collapsible';
import type { VscCollapsibleToggleEvent } from '@vscode-elements/elements/dist/vscode-collapsible/vscode-collapsible';
import '@vscode-elements/elements/dist/vscode-form-container';
import { useCallback, useState } from 'react';
import type { UpdateRequestedData } from '../inspector-data/messages';
import { useCallback, useEffect, useState } from 'react';
import type { CollapsibleStateData, UpdateRequestedData } from '../inspector-data/messages';
import { UpdateRequested } from '../inspector-data/messages';
import type { TypedValue } from '../inspector-data/types';
import { usePublisher } from '../messenger/usePublisher';
import { reportCollapsibleState } from './collapsibleReporter';
import { DynamicValue } from './DynamicValue';
import { ErrorCard } from './ErrorCard';
import type { ValueUpdated } from './valueProps';

interface TypedValueDetailsProps {
typedValue: TypedValue;
collapsibleState?: CollapsibleStateData;
}

export function TypedValueDetails({ typedValue }: TypedValueDetailsProps) {
export function TypedValueDetails({ typedValue, collapsibleState }: TypedValueDetailsProps) {
const [requestData, setRequestData] = useState<UpdateRequestedData>();
usePublisher(UpdateRequested, requestData);
const [open, setOpen] = useState(false);

const collapsibleKey = typedValue.schema.typePath;

useEffect(() => {
return () => {
reportCollapsibleState(collapsibleKey, false);
};
}, [collapsibleKey]);

useEffect(() => {
if (collapsibleState !== undefined) {
setOpen(collapsibleState.anyExpanded);
reportCollapsibleState(collapsibleKey, collapsibleState.anyExpanded);
}
}, [collapsibleState, collapsibleKey]);

const onToggle = useCallback(
(e: VscCollapsibleToggleEvent) => {
const expanded = e.detail.open;
setOpen(expanded);
reportCollapsibleState(collapsibleKey, expanded);
},
[collapsibleKey],
);

if (typedValue.error || !typedValue.schema) {
const errorMessage = typedValue.error || 'No schema found.';
Expand Down Expand Up @@ -43,7 +71,12 @@ export function TypedValueDetails({ typedValue }: TypedValueDetailsProps) {

return (
<vscode-form-container>
<vscode-collapsible title={typedValue.schema.shortPath} description={typedValue.schema.typePath}>
<vscode-collapsible
title={typedValue.schema.shortPath}
description={typedValue.schema.typePath}
open={open}
onvsc-collapsible-toggle={onToggle}
>
<DynamicValue path="" value={typedValue.value} schema={typedValue.schema} onValueChange={onValueChange} />
</vscode-collapsible>
</vscode-form-container>
Expand Down
21 changes: 21 additions & 0 deletions src/schema-components/collapsibleReporter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { CollapsibleStateChanged } from '../inspector-data/messages';
import { vscodeMessenger } from '../messenger/vscodeMessenger';

const expandedKeys = new Set<string>();
let previouslyAnyExpanded: boolean | undefined;

export function reportCollapsibleState(key: string, expanded: boolean): void {
if (expanded) {
expandedKeys.add(key);
} else {
expandedKeys.delete(key);
}
const anyExpanded = expandedKeys.size > 0;
if (previouslyAnyExpanded !== anyExpanded) {
previouslyAnyExpanded = anyExpanded;
vscodeMessenger.publishEvent({
type: CollapsibleStateChanged,
data: { anyExpanded },
});
}
}