Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
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
12 changes: 12 additions & 0 deletions editor/src/dashboard/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuSepara

import { isDarwin } from "../tools/os";
import { ProjectType } from "../tools/project";
import { openInIde } from "../tools/ide";
import { execNodePty, NodePtyInstance } from "../tools/node-pty";

import { IEditorProject } from "../project/typings";
Expand Down Expand Up @@ -142,6 +143,11 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
execNodePty(`code "${dirname(props.project.absolutePath)}"`);
}

function handleOpenInDefaultIde() {
const projectDir = dirname(props.project.absolutePath);
openInIde(projectDir, true);
}

return (
<ContextMenu onOpenChange={(o) => setContextMenuOpen(o)}>
<ContextMenuTrigger>
Expand Down Expand Up @@ -185,6 +191,9 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
{`Show in ${isDarwin() ? "Finder" : "Explorer"}`}
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem className="flex items-center gap-2" onClick={() => handleOpenInDefaultIde()}>
Open in Default IDE
</DropdownMenuItem>
<DropdownMenuItem className="flex items-center gap-2" onClick={() => handleOpenInVisualStudioCode()}>
Open in Visual Studio Code
</DropdownMenuItem>
Expand Down Expand Up @@ -237,6 +246,9 @@ export function DashboardProjectItem(props: IDashboardProjectItemProps) {
{`Show in ${isDarwin() ? "Finder" : "Explorer"}`}
</ContextMenuItem>
<ContextMenuSeparator />
<ContextMenuItem className="flex items-center gap-2" onClick={() => handleOpenInDefaultIde()}>
Open in Default IDE
</ContextMenuItem>
<ContextMenuItem className="flex items-center gap-2" onClick={() => handleOpenInVisualStudioCode()}>
Open in Visual Studio Code
</ContextMenuItem>
Expand Down
39 changes: 38 additions & 1 deletion editor/src/editor/dialogs/edit-preferences/edit-preferences.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,12 @@ import { Separator } from "../../../ui/shadcn/ui/separator";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../../../ui/shadcn/ui/select";
import { AlertDialog, AlertDialogCancel, AlertDialogContent, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle } from "../../../ui/shadcn/ui/alert-dialog";

import { trySetExperimentalFeaturesEnabledInLocalStorage } from "../../../tools/local-storage";
import {
defaultIdeOptions,
tryGetDefaultIdeFromLocalStorage,
trySetDefaultIdeInLocalStorage,
trySetExperimentalFeaturesEnabledInLocalStorage,
} from "../../../tools/local-storage";

import { EditorInspectorKeyField } from "../../layout/inspector/fields/key";
import { EditorInspectorNumberField } from "../../layout/inspector/fields/number";
Expand All @@ -28,6 +33,7 @@ export interface IEditorEditPreferencesComponentProps {

export interface IEditorEditPreferencesComponentState {
theme: "light" | "dark";
defaultIde: string;
}

export class EditorEditPreferencesComponent extends Component<IEditorEditPreferencesComponentProps, IEditorEditPreferencesComponentState> {
Expand All @@ -36,6 +42,7 @@ export class EditorEditPreferencesComponent extends Component<IEditorEditPrefere

this.state = {
theme: document.body.classList.contains("dark") ? "dark" : "light",
defaultIde: tryGetDefaultIdeFromLocalStorage(),
};
}

Expand All @@ -51,6 +58,8 @@ export class EditorEditPreferencesComponent extends Component<IEditorEditPrefere
<Separator />
{this._getThemesComponent()}
<Separator />
{this._getDefaultIdeComponent()}
<Separator />
{this._getCameraControlPreferences()}
<Separator />
{this._getExperimentalComponent()}
Expand Down Expand Up @@ -96,6 +105,34 @@ export class EditorEditPreferencesComponent extends Component<IEditorEditPrefere
);
}

private _getDefaultIdeComponent(): ReactNode {
return (
<div className="flex flex-col gap-[10px] w-full">
<div className="flex flex-col gap-[10px]">
<Label className="text-xl font-[400]">Default IDE</Label>
<Select
value={this.state.defaultIde}
onValueChange={(v) => {
this.setState({ defaultIde: v });
trySetDefaultIdeInLocalStorage(v);
}}
>
<SelectTrigger className="">
<SelectValue placeholder="Select Value..." />
</SelectTrigger>
<SelectContent>
{defaultIdeOptions.map((option) => (
<SelectItem key={option.id} value={option.id}>
{option.label}
</SelectItem>
))}
</SelectContent>
</Select>
</div>
</div>
);
}

private _getCameraControlPreferences(): ReactNode {
const camera = this.props.editor.layout?.preview?.camera;
if (!camera) {
Expand Down
19 changes: 13 additions & 6 deletions editor/src/editor/layout/assets-browser/items/item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ import { Grid } from "react-loader-spinner";

import { toast } from "sonner";

import { ImFinder } from "react-icons/im";
import { BiSolidFileCss } from "react-icons/bi";
import { GiCeilingLight } from "react-icons/gi";
import { GrStatusUnknown } from "react-icons/gr";
Expand All @@ -27,6 +26,7 @@ import { Input } from "../../../../ui/shadcn/ui/input";
import { ContextMenu, ContextMenuContent, ContextMenuItem, ContextMenuTrigger, ContextMenuSeparator } from "../../../../ui/shadcn/ui/context-menu";

import { isDarwin } from "../../../../tools/os";
import { openInIde } from "../../../../tools/ide";

import { Editor } from "../../../main";

Expand Down Expand Up @@ -250,7 +250,10 @@ export class AssetsBrowserItem extends Component<IAssetsBrowserItemProps, IAsset
* Called on the item is double-clicked. To be overriden by the specialized items implementations.
*/
protected onDoubleClick(): void | Promise<void> {
// Nothing to do by default.
// If it's a file (not a directory), open it in the default editor
if (!this.state.isDirectory) {
openInIde(this.props.absolutePath, false);
}
}

private _handleDragStart(ev: DragEvent<HTMLDivElement>): void {
Expand Down Expand Up @@ -392,12 +395,16 @@ export class AssetsBrowserItem extends Component<IAssetsBrowserItemProps, IAsset

return (
<ContextMenuContent>
{!this.state.isDirectory && (
<ContextMenuItem className="flex items-center gap-2" onClick={() => openInIde(this.props.absolutePath, false)}>
Open
</ContextMenuItem>
)}

<ContextMenuItem className="flex items-center gap-2" onClick={() => ipcRenderer.send("editor:show-item", this.props.absolutePath)}>
<ImFinder className="w-4 h-4" /> {`Show in ${isDarwin ? "Finder" : "Explorer"}`}
{`Show in ${isDarwin ? "Finder" : "Explorer"}`}
</ContextMenuItem>

<ContextMenuSeparator />

{items.map((item, index) => (
<Fragment key={`context-menu-item-${index}`}>{item}</Fragment>
))}
Expand All @@ -418,7 +425,7 @@ export class AssetsBrowserItem extends Component<IAssetsBrowserItemProps, IAsset
<ContextMenuSeparator />

<ContextMenuItem className="flex items-center gap-2 !text-red-400" onClick={() => this._handleTrashItem()}>
<AiOutlineClose className="w-5 h-5" fill="rgb(248, 113, 113)" /> Remove
<AiOutlineClose className="w-5 h-5" fill="rgb(248, 113, 113)" /> Delete
</ContextMenuItem>
</ContextMenuContent>
);
Expand Down
15 changes: 15 additions & 0 deletions editor/src/editor/layout/toolbar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
} from "../../ui/shadcn/ui/menubar";

import { isDarwin } from "../../tools/os";
import { openInIde } from "../../tools/ide";
import { execNodePty } from "../../tools/node-pty";
import { openSingleFileDialog } from "../../tools/dialog";
import { saveSceneScreenshot } from "../../tools/scene/screenshot";
Expand Down Expand Up @@ -55,6 +56,7 @@ export class EditorToolbar extends Component<IEditorToolbarProps> {
super(props);

ipcRenderer.on("editor:open-project", () => this._handleOpenProject());
ipcRenderer.on("editor:open-default-ide", () => this._handleOpenInDefaultIde());
ipcRenderer.on("editor:open-vscode", () => this._handleOpenVisualStudioCode());
ipcRenderer.on("editor:toggle-marketplace", () => this._handleToggleMarketplace());

Expand Down Expand Up @@ -110,6 +112,10 @@ export class EditorToolbar extends Component<IEditorToolbarProps> {

<MenubarSeparator />

<MenubarItem disabled={!this.props.editor.state.projectPath} onClick={() => this._handleOpenInDefaultIde()}>
Open in Default IDE
</MenubarItem>

<MenubarItem disabled={!this.props.editor.state.visualStudioCodeAvailable} onClick={() => this._handleOpenVisualStudioCode()}>
Open in Visual Studio Code
</MenubarItem>
Expand Down Expand Up @@ -314,6 +320,15 @@ export class EditorToolbar extends Component<IEditorToolbarProps> {
await p.wait();
}

private _handleOpenInDefaultIde(): void {
if (!this.props.editor.state.projectPath) {
return;
}

const projectDir = dirname(this.props.editor.state.projectPath);
openInIde(projectDir, true);
}

private _handleToggleMarketplace(): void {
if (this.props.editor.state.openedTabs.includes("marketplace")) {
return this.props.editor.layout.removeLayoutTab("marketplace");
Expand Down
4 changes: 4 additions & 0 deletions editor/src/editor/menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,10 @@ export function setupEditorMenu(options: { enableExperimentalFeatures: boolean;
{
type: "separator",
},
{
label: "Open in Default IDE",
click: () => BrowserWindow.getFocusedWindow()?.webContents.send("editor:open-default-ide"),
},
{
label: "Open in Visual Studio Code",
click: () => BrowserWindow.getFocusedWindow()?.webContents.send("editor:open-vscode"),
Expand Down
51 changes: 29 additions & 22 deletions editor/src/electron/events/shell.ts
Original file line number Diff line number Diff line change
@@ -1,22 +1,29 @@
import { platform } from "os";
import { ipcMain, shell } from "electron";

ipcMain.on("editor:trash-items", async (ev, items) => {
const isWindows = platform() === "win32";
items = items.map((item) => (isWindows ? item.replace(/\//g, "\\") : item.replace(/\\/g, "/")));

try {
await Promise.all(items.map((item) => shell.trashItem(item)));
ev.returnValue = true;
} catch (e) {
console.error(e);
ev.returnValue = false;
}
});

ipcMain.on("editor:show-item", (_, item) => {
const isWindows = platform() === "win32";
item = isWindows ? item.replace(/\//g, "\\") : item.replace(/\\/g, "/");

shell.showItemInFolder(item);
});
import { platform } from "os";
import { ipcMain, shell } from "electron";

ipcMain.on("editor:trash-items", async (ev, items) => {
const isWindows = platform() === "win32";
items = items.map((item) => (isWindows ? item.replace(/\//g, "\\") : item.replace(/\\/g, "/")));

try {
await Promise.all(items.map((item) => shell.trashItem(item)));
ev.returnValue = true;
} catch (e) {
console.error(e);
ev.returnValue = false;
}
});

ipcMain.on("editor:show-item", (_, item) => {
const isWindows = platform() === "win32";
item = isWindows ? item.replace(/\//g, "\\") : item.replace(/\\/g, "/");

shell.showItemInFolder(item);
});

ipcMain.on("editor:open-in-external-editor", (_, item) => {
const isWindows = platform() === "win32";
item = isWindows ? item.replace(/\//g, "\\") : item.replace(/\\/g, "/");

shell.openPath(item);
});
Loading