Skip to content

Update window-layouts extension#27013

Open
gfazioli wants to merge 3 commits intoraycast:mainfrom
gfazioli:ext/window-layouts
Open

Update window-layouts extension#27013
gfazioli wants to merge 3 commits intoraycast:mainfrom
gfazioli:ext/window-layouts

Conversation

@gfazioli
Copy link
Copy Markdown
Contributor

@gfazioli gfazioli commented Apr 8, 2026

Description

Screencast

Checklist

- * ✨ feat: add new layouts, smart commands, save/restore, and custom layouts
- Pull contributions
@raycastbot raycastbot added extension fix / improvement Label for PRs with extension's fix improvements extension: window-layouts Issues related to the window-layouts extension platform: macOS OP is contributor The OP of the PR is a contributor of the extension labels Apr 8, 2026
@raycastbot
Copy link
Copy Markdown
Collaborator

raycastbot commented Apr 8, 2026

Thank you for your contribution! 🎉

🔔 @teemusuvinen you might want to have a look.

You can use this guide to learn how to check out the Pull Request locally in order to test it.

📋 Quick checkout commands
BRANCH="ext/window-layouts"
FORK_URL="https://github.com/gfazioli/raycast-extensions.git"
EXTENSION_NAME="window-layouts"
REPO_NAME="raycast-extensions"

git clone -n --depth=1 --filter=tree:0 -b $BRANCH $FORK_URL
cd $REPO_NAME
git sparse-checkout set --no-cone "extensions/$EXTENSION_NAME"
git checkout
cd "extensions/$EXTENSION_NAME"
npm install && npm run dev

We're currently experiencing a high volume of incoming requests. As a result, the initial review may take up to 10-15 business days.

@gfazioli gfazioli marked this pull request as ready for review April 8, 2026 17:12
Copilot AI review requested due to automatic review settings April 8, 2026 17:12
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Note

Copilot was unable to run its full agentic suite in this review.

Updates the window-layouts Raycast extension by adding more built-in layouts and introducing “smart”/custom workflows (auto layout, picking layout with window reordering, saving/restoring, custom layouts), alongside refactors to centralize desktop/window discovery and enable layout reuse.

Changes:

  • Added new layouts (75/25 splits, 3x3, 6-grid, centered focus, PiP) and corresponding no-view commands.
  • Introduced new view commands: pick layout (with ordering), auto layout, save/restore layouts, and create/browse custom layouts.
  • Refactored layout utilities (desktop context, preference parsing, exported helpers) and updated docs/changelog.

Reviewed changes

Copilot reviewed 27 out of 41 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
extensions/window-layouts/src/vertical-75-25.ts Adds a new command that applies the vertical 75/25 layout.
extensions/window-layouts/src/vertical-25-75.ts Adds a new command that applies the vertical 25/75 layout.
extensions/window-layouts/src/utils/saved-layouts.ts Adds LocalStorage persistence helpers for saved window placements.
extensions/window-layouts/src/utils/layout/window-layouts.ts Adds multiple new preset layout definitions (grids, splits, special).
extensions/window-layouts/src/utils/layout/index.ts Re-exports new layouts and newly exported layout helper functions.
extensions/window-layouts/src/utils/layout/create-layout.ts Refactors layout application around DesktopContext; exports helpers; improves failure reporting.
extensions/window-layouts/src/utils/index.ts Updates exports to include DesktopContext + layout helper exports.
extensions/window-layouts/src/utils/get-user-preferences.ts Makes preferences access synchronous; adds excludedApps parsing.
extensions/window-layouts/src/utils/get-resizable-windows.ts Removes old window discovery helper (superseded by getDesktopContext).
extensions/window-layouts/src/utils/get-desktop-context.ts Adds unified desktop + filtered window discovery (including excluded apps).
extensions/window-layouts/src/utils/get-active-desktop.ts Removes old desktop discovery helper (superseded by getDesktopContext).
extensions/window-layouts/src/utils/custom-layouts.ts Adds LocalStorage persistence helpers for user-defined JSON grid layouts.
extensions/window-layouts/src/save-layout.tsx Adds UI to save current window positions to LocalStorage.
extensions/window-layouts/src/restore-layout.tsx Adds UI to browse and restore saved layouts by app-name matching.
extensions/window-layouts/src/pip.ts Adds a new command that applies the PiP layout.
extensions/window-layouts/src/pick-layout.tsx Adds UI to reorder windows and apply a chosen layout by slot order.
extensions/window-layouts/src/horizontal-75-25.ts Adds a new command that applies the horizontal 75/25 layout.
extensions/window-layouts/src/horizontal-25-75.ts Adds a new command that applies the horizontal 25/75 layout.
extensions/window-layouts/src/grid-6.ts Adds a new command that applies the 3x2 grid layout.
extensions/window-layouts/src/grid-3x3.ts Adds a new command that applies the 3x3 grid layout.
extensions/window-layouts/src/custom-layouts.tsx Adds UI to list/apply/delete custom layouts.
extensions/window-layouts/src/create-custom-layout.tsx Adds UI to create and validate custom layouts from JSON.
extensions/window-layouts/src/centered-focus.ts Adds a new command that applies the centered focus layout.
extensions/window-layouts/src/auto-layout.ts Adds a command that chooses a layout based on window count.
extensions/window-layouts/package.json Registers new commands/preferences and fixes a typo in an existing description.
extensions/window-layouts/README.md Updates documentation to cover new layouts, commands, and preferences.
extensions/window-layouts/CHANGELOG.md Documents newly added features/refactors and bug fixes.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Apr 8, 2026

Greptile Summary

This PR significantly expands the window-layouts extension with eight new layout commands (75/25 splits, grids of 6 and 9, Centered Focus, Picture-in-Picture), six new view-type commands (Auto Layout, Pick Layout, Save/Restore Layout, Create/Browse Custom Layouts), an excludedApps preference, and several bug fixes including the animated toast leak on early return and silent swallowing of applyLayout failures.

Confidence Score: 5/5

Safe to merge — all findings are P2 style/consistency suggestions with no blocking issues.

The core logic is sound: the unified getDesktopContext helper, failure-count reporting, and new layout definitions all look correct. Both open findings are P2: a manually defined Preferences type (should use the auto-generated one) and a missing popToRoot() in save-layout.tsx.

extensions/window-layouts/src/utils/get-user-preferences.ts and extensions/window-layouts/src/save-layout.tsx have minor style issues worth addressing.

Vulnerabilities

No security concerns identified. User-supplied layout names and grid JSON are only stored in Raycast LocalStorage and never executed or sent to external services. The excludedApps preference is compared case-insensitively against window application names and poses no injection risk.

Important Files Changed

Filename Overview
extensions/window-layouts/src/utils/get-user-preferences.ts Refactored to synchronous; correctly fixes NaN gap fallback; but manually defines UserPreferences type instead of using the auto-generated Preferences from raycast-env.d.ts
extensions/window-layouts/src/save-layout.tsx New command to save window positions; missing popToRoot() after successful save unlike the sibling create-custom-layout command
extensions/window-layouts/src/utils/get-desktop-context.ts New unified helper replacing getActiveDesktop + getResizableWindows; correctly awaits toast calls, parallelises API calls, and applies excludedApps filter
extensions/window-layouts/src/utils/layout/create-layout.ts Exported calculateCellSize/getWindowFrames; applyLayout now returns failure count and animated toast is hidden on early returns; getUserPreferences correctly made synchronous
extensions/window-layouts/src/pick-layout.tsx New view command to reorder windows before applying a layout; logic is sound
extensions/window-layouts/src/restore-layout.tsx New command to restore saved layouts; correctly handles multiple windows from the same app with a usedWindowIds set
extensions/window-layouts/src/create-custom-layout.tsx New view command for JSON-based custom layout creation; validation and popToRoot on success are correct
extensions/window-layouts/src/auto-layout.ts New no-view command that maps window count to an appropriate layout; falls back to GRID_3X3 for 10+ windows
extensions/window-layouts/package.json New commands and excludedApps preference added; titles use Title Case; typo in vertical-50-50 description fixed
extensions/window-layouts/CHANGELOG.md New entry correctly uses {PR_MERGE_DATE} placeholder and is placed at the top of the file

Fix All in Codex Fix All in Cursor Fix All in Claude Code

Prompt To Fix All With AI
This is a comment left during a code review.
Path: extensions/window-layouts/src/utils/get-user-preferences.ts
Line: 3-9

Comment:
**Manually defined Preferences type**

`UserPreferences` is a hand-written type for `getPreferenceValues()`, which is flagged by the project's rules. Raycast auto-generates the `Preferences` interface in `raycast-env.d.ts` when the extension runs, so a manual definition can drift out of sync with `package.json`. Use the generated type instead:

```suggestion
import { getPreferenceValues } from "@raycast/api";

export function getUserPreferences() {
  const userPreferences = getPreferenceValues<Preferences>();
  const gap = parseInt(userPreferences.gap as string, 10);
  const rawExcluded = (userPreferences.excludedApps as string) ?? "";
```

**Rule Used:** What: Don't manually define `Preferences` for `get... ([source](https://app.greptile.com/review/custom-context?memory=d93fc9fb-a45d-4479-a6a4-b1b4af98ebc8))

How can I resolve this? If you propose a fix, please make it concise.

---

This is a comment left during a code review.
Path: extensions/window-layouts/src/save-layout.tsx
Line: 33-42

Comment:
**Missing `popToRoot()` after successful save**

`create-custom-layout.tsx` calls `popToRoot()` after a successful submit, but `save-layout.tsx` does not — leaving the form open after the success toast. Consider adding it for consistency:

```suggestion
    await saveLayout({
      name,
      windows,
      savedAt: new Date().toISOString(),
    });

    await showToast({
      style: Toast.Style.Success,
      title: `Layout "${name}" saved`,
      message: `${windows.length} window(s)`,
    });
    await popToRoot();
```

How can I resolve this? If you propose a fix, please make it concise.

Reviews (1): Last reviewed commit: "Update window-layouts extension" | Re-trigger Greptile

gfazioli and others added 2 commits April 9, 2026 07:06
- Use auto-generated Preferences type instead of manual UserPreferences
- Add popToRoot() after successful save in save-layout
- Use structural type guard for w.bounds instead of forced cast
- Respect disableToasts preference in pick-layout
- Update catch block in create-layout to reuse toast instead of creating new one
- Guard gridPreview against empty/invalid grids in custom-layouts

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Merge branch \'contributions/merge-1775742411252\'
- Pull contributions
- fix: address PR review feedback and compress metadata images
@teemusuvinen
Copy link
Copy Markdown
Contributor

Hi @gfazioli ! Thank you for contributing, pretty cool features it seems 🙌 Is this ready for review or are you still working on it?

@gfazioli
Copy link
Copy Markdown
Contributor Author

gfazioli commented Apr 9, 2026

Hi @gfazioli ! Thank you for contributing, pretty cool features it seems 🙌 Is this ready for review or are you still working on it?

Hi @teemusuvinen! Thank you 🙏 Yes, it's ready for review — I'm not actively working on it anymore. All the review feedback from Copilot and Greptile has already been addressed in the latest commits. Looking forward to your review!

Comment on lines +25 to +29
async function handleDelete(layout: CustomLayout) {
await deleteCustomLayout(layout.name);
await loadLayouts();
await showToast({ style: Toast.Style.Success, title: `Deleted "${layout.name}"` });
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a confirm dialog before deleting a layout to avoid accidental deletions:

Suggested change
async function handleDelete(layout: CustomLayout) {
await deleteCustomLayout(layout.name);
await loadLayouts();
await showToast({ style: Toast.Style.Success, title: `Deleted "${layout.name}"` });
}
async function handleDelete(layout: CustomLayout) {
const isConfirmed = await confirmAlert({
title: `Delete "${layout.name}"?`,
primaryAction: { title: "Delete", style: Alert.ActionStyle.Destructive },
dismissAction: { title: "Cancel" },
// rememberUserChoice: true <-- optionally with "Do not show this message again" checkbox
});
if (!isConfirmed) return;
await deleteCustomLayout(layout.name);
await loadLayouts();
await showToast({ style: Toast.Style.Success, title: `Deleted "${layout.name}"` });
}

{layouts.length === 0 && !isLoading ? (
<List.EmptyView
title="No Custom Layouts"
description="Use 'Create Custom Layout' to define your own grid layouts."
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here could be an action to easily navigate to the "Create Custom Layout" command:

async function handleCreate() {
  // this will pop back to custom layouts list after a new layout has been created
  pop();
  await loadLayouts();
}

.....

actions={
  <ActionPanel>
    <Action.Push
      target={<CreateCustomLayout onCreate={handleCreate} />}
      title="Create Custom Layout"
      icon={Icon.Plus}
      shortcut={Keyboard.Shortcut.Common.New}
    />
  </ActionPanel>
}

.....

// create-custom-layout.tsx

type CreateCustomLayoutProps = {
  onCreate?: () => void;
};

export default function Command({ onCreate }: CreateCustomLayoutProps) {

.....

async function handleSubmit(values: { name: string; grid: string }) {

....

  await showToast({
    style: Toast.Style.Success,
    title: `Layout "${name}" created`,
  });

  if (onCreate) {
    onCreate();
    return;
  }

  await popToRoot();
}

title="Delete Layout"
icon={Icon.Trash}
style={Action.Style.Destructive}
shortcut={{ modifiers: ["cmd"], key: "d" }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is probably personal preference but my muscle-memory for deleting things in Raycast would want to use the common delete shortcut ctrl+x 😄

// import { Keyboard } from "@raycast/api"
shortcut={Keyboard.Shortcut.Common.Remove}

Comment on lines +35 to +36
layouts[existing] = layout;
} else {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a confirm dialog here to prevent accidental overwrites to existing layouts

Suggested change
layouts[existing] = layout;
} else {
const isConfirmed = await confirmAlert({
title: `A layout named "${layout.name}" already exists. Do you want to overwrite it?`,
primaryAction: { title: "Overwrite", style: Alert.ActionStyle.Destructive },
dismissAction: { title: "Cancel" },
// rememberUserChoice: true <-- optionally with "Do not show this message again" checkbox
});
if (!isConfirmed) return;
layouts[existing] = layout;
} else {

<Action
title="Move Down"
icon={Icon.ArrowDown}
shortcut={{ modifiers: ["cmd"], key: "arrowDown" }}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cmd+arrowUp and cmd+arrowDown don't seem to work on my keyboard - it just jumps between the List.Section elements

<List.Item
key={w.id}
title={`${i + 1}. ${w.application?.name ?? "Unknown"}`}
icon={Icon.Window}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could show the application icon here:

icon={w.application?.path ? { fileIcon: w.application.path } : Icon.Window}
Image

Comment on lines +15 to +37
const AVAILABLE_LAYOUTS: NamedLayout[] = [
{ name: "Horizontal 50/50", layout: layouts.HORIZONTAL_50_50, slots: 2 },
{ name: "Horizontal 70/30", layout: layouts.HORIZONTAL_70_30, slots: 2 },
{ name: "Horizontal 30/70", layout: layouts.HORIZONTAL_30_70, slots: 2 },
{ name: "Horizontal 75/25", layout: layouts.HORIZONTAL_75_25, slots: 2 },
{ name: "Horizontal 25/75", layout: layouts.HORIZONTAL_25_75, slots: 2 },
{ name: "Horizontal 3 Columns", layout: layouts.HORIZONTAL_3, slots: 3 },
{ name: "Horizontal 1+2", layout: layouts.HORIZONTAL_1_2, slots: 3 },
{ name: "Horizontal 2+1", layout: layouts.HORIZONTAL_2_1, slots: 3 },
{ name: "Vertical 50/50", layout: layouts.VERTICAL_50_50, slots: 2 },
{ name: "Vertical 70/30", layout: layouts.VERTICAL_70_30, slots: 2 },
{ name: "Vertical 30/70", layout: layouts.VERTICAL_30_70, slots: 2 },
{ name: "Vertical 75/25", layout: layouts.VERTICAL_75_25, slots: 2 },
{ name: "Vertical 25/75", layout: layouts.VERTICAL_25_75, slots: 2 },
{ name: "Vertical 3 Rows", layout: layouts.VERTICAL_3, slots: 3 },
{ name: "Vertical 1+2", layout: layouts.VERTICAL_1_2, slots: 3 },
{ name: "Vertical 2+1", layout: layouts.VERTICAL_2_1, slots: 3 },
{ name: "Grid of 4", layout: layouts.GRID, slots: 4 },
{ name: "Grid of 6", layout: layouts.GRID_6, slots: 6 },
{ name: "Grid of 9", layout: layouts.GRID_3X3, slots: 9 },
{ name: "Centered Focus", layout: layouts.CENTERED_FOCUS, slots: 3 },
{ name: "Picture in Picture", layout: layouts.PIP, slots: 2 },
];
Copy link
Copy Markdown
Contributor

@teemusuvinen teemusuvinen Apr 9, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add the actual layout icons here:

Suggested change
const AVAILABLE_LAYOUTS: NamedLayout[] = [
{ name: "Horizontal 50/50", layout: layouts.HORIZONTAL_50_50, slots: 2 },
{ name: "Horizontal 70/30", layout: layouts.HORIZONTAL_70_30, slots: 2 },
{ name: "Horizontal 30/70", layout: layouts.HORIZONTAL_30_70, slots: 2 },
{ name: "Horizontal 75/25", layout: layouts.HORIZONTAL_75_25, slots: 2 },
{ name: "Horizontal 25/75", layout: layouts.HORIZONTAL_25_75, slots: 2 },
{ name: "Horizontal 3 Columns", layout: layouts.HORIZONTAL_3, slots: 3 },
{ name: "Horizontal 1+2", layout: layouts.HORIZONTAL_1_2, slots: 3 },
{ name: "Horizontal 2+1", layout: layouts.HORIZONTAL_2_1, slots: 3 },
{ name: "Vertical 50/50", layout: layouts.VERTICAL_50_50, slots: 2 },
{ name: "Vertical 70/30", layout: layouts.VERTICAL_70_30, slots: 2 },
{ name: "Vertical 30/70", layout: layouts.VERTICAL_30_70, slots: 2 },
{ name: "Vertical 75/25", layout: layouts.VERTICAL_75_25, slots: 2 },
{ name: "Vertical 25/75", layout: layouts.VERTICAL_25_75, slots: 2 },
{ name: "Vertical 3 Rows", layout: layouts.VERTICAL_3, slots: 3 },
{ name: "Vertical 1+2", layout: layouts.VERTICAL_1_2, slots: 3 },
{ name: "Vertical 2+1", layout: layouts.VERTICAL_2_1, slots: 3 },
{ name: "Grid of 4", layout: layouts.GRID, slots: 4 },
{ name: "Grid of 6", layout: layouts.GRID_6, slots: 6 },
{ name: "Grid of 9", layout: layouts.GRID_3X3, slots: 9 },
{ name: "Centered Focus", layout: layouts.CENTERED_FOCUS, slots: 3 },
{ name: "Picture in Picture", layout: layouts.PIP, slots: 2 },
];
const AVAILABLE_LAYOUTS: NamedLayout[] = [
{ icon: "horizontal-50-50.png", name: "Horizontal 50/50", layout: layouts.HORIZONTAL_50_50, slots: 2 },
{ icon: "horizontal-70-30.png", name: "Horizontal 70/30", layout: layouts.HORIZONTAL_70_30, slots: 2 },
{ icon: "horizontal-30-70.png", name: "Horizontal 30/70", layout: layouts.HORIZONTAL_30_70, slots: 2 },
{ icon: "horizontal-75-25.png", name: "Horizontal 75/25", layout: layouts.HORIZONTAL_75_25, slots: 2 },
{ icon: "horizontal-25-75.png", name: "Horizontal 25/75", layout: layouts.HORIZONTAL_25_75, slots: 2 },
{ icon: "horizontal-3.png", name: "Horizontal 3 Columns", layout: layouts.HORIZONTAL_3, slots: 3 },
{ icon: "horizontal-1-2.png", name: "Horizontal 1+2", layout: layouts.HORIZONTAL_1_2, slots: 3 },
{ icon: "horizontal-2-1.png", name: "Horizontal 2+1", layout: layouts.HORIZONTAL_2_1, slots: 3 },
{ icon: "vertical-50-50.png", name: "Vertical 50/50", layout: layouts.VERTICAL_50_50, slots: 2 },
{ icon: "vertical-70-30.png", name: "Vertical 70/30", layout: layouts.VERTICAL_70_30, slots: 2 },
{ icon: "vertical-30-70.png", name: "Vertical 30/70", layout: layouts.VERTICAL_30_70, slots: 2 },
{ icon: "vertical-75-25.png", name: "Vertical 75/25", layout: layouts.VERTICAL_75_25, slots: 2 },
{ icon: "vertical-25-75.png", name: "Vertical 25/75", layout: layouts.VERTICAL_25_75, slots: 2 },
{ icon: "vertical-3.png", name: "Vertical 3 Rows", layout: layouts.VERTICAL_3, slots: 3 },
{ icon: "vertical-1-2.png", name: "Vertical 1+2", layout: layouts.VERTICAL_1_2, slots: 3 },
{ icon: "vertical-2-1.png", name: "Vertical 2+1", layout: layouts.VERTICAL_2_1, slots: 3 },
{ icon: "grid.png", name: "Grid of 4", layout: layouts.GRID, slots: 4 },
{ icon: "grid-6.png", name: "Grid of 6", layout: layouts.GRID_6, slots: 6 },
{ icon: "grid-3x3.png", name: "Grid of 9", layout: layouts.GRID_3X3, slots: 9 },
{ icon: "centered-focus.png", name: "Centered Focus", layout: layouts.CENTERED_FOCUS, slots: 3 },
{ icon: "pip.png", name: "Picture in Picture", layout: layouts.PIP, slots: 2 },
];

We can then show the actual layout icon here instead of a generic grid icon

{matchingLayouts.map((nl) => (
  <List.Item
    ....
    // Actual icon here instead of generic 2x2 grid 🙂 
    icon={{ source: `icons/${nl.icon}` }}
Image

await deleteSavedLayout(layout.name);
await loadLayouts();
await showToast({ style: Toast.Style.Success, title: `Deleted "${layout.name}"` });
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could show a confirm dialog here to avoid accidental deletions

async function handleDelete(layout: SavedLayout) {
  const isConfirmed = await confirmAlert({
    title: `Delete "${layout.name}"?`,
    primaryAction: { title: "Delete", style: Alert.ActionStyle.Destructive },
    dismissAction: { title: "Cancel" },
    // rememberUserChoice: true <-- optionally with "Do not show this message again" checkbox
  });

  if (!isConfirmed) return;

  await deleteCustomLayout(layout.name);
  await loadLayouts();
  await showToast({ style: Toast.Style.Success, title: `Deleted "${layout.name}"` });
}

export async function saveCustomLayout(layout: CustomLayout): Promise<void> {
const all = await getCustomLayouts();
const existing = all.findIndex((l) => l.name === layout.name);
if (existing >= 0) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a confirm dialog here to prevent accidental overwrites to existing layouts

const isConfirmed = await confirmAlert({
  title: `A layout named "${layout.name}" already exists. Do you want to overwrite it?`,
  primaryAction: { title: "Overwrite", style: Alert.ActionStyle.Destructive },
  dismissAction: { title: "Cancel" },
  // rememberUserChoice: true <-- optionally with "Do not show this message again" checkbox
});

if (!isConfirmed) return;

all[existing] = layout;

@teemusuvinen
Copy link
Copy Markdown
Contributor

@gfazioli I have now checked the PR and added mostly suggestions to enhance the functionality but overall super nice work and useful additions! 🙏 Feel free to also send me a message in Raycast Slack if you want to discuss something in more detail 🙂

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

extension fix / improvement Label for PRs with extension's fix improvements extension: window-layouts Issues related to the window-layouts extension OP is contributor The OP of the PR is a contributor of the extension platform: macOS

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants