Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Rotate panes #496

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open

Rotate panes #496

wants to merge 4 commits into from

Conversation

Hen2609
Copy link

@Hen2609 Hen2609 commented Oct 20, 2024

Added rotate panes functionality.
one bug I can't find the source of yet, after rotating a mixed layout:
|-----1------|
|--2--|--3--|
after deleting the middle pane, and than the bottom pane, the top pane won't resize.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added a "Rotate active layout" button to the navigation bar for enhanced layout control.
    • Introduced functionality to dynamically change layout direction between "topbottom" and "rightleft".
    • Users can now swap panes using keyboard shortcuts while holding the Shift key.
    • Added a feature to view the changelog directly within the application.
  • Bug Fixes

    • Improved error handling in pane fitting logic to ensure better reliability.
  • Refactor

    • Enhanced pane management capabilities with new methods for pane retrieval and swapping.

Introduced a new "Rotate active layout" button to the interface and implemented functionality for switching the pane directions between top-bottom and right-left. Modified `window.ts` to break down `moveFocus` and added `switchPane` for future use. Adjusted `pane.ts` to handle new pane direction switching logic. Added method `changeDir` in `layout.ts` for rotating the pane orientation.
Changed the data-sc attribute for the rotate button to "⇧ R" to better indicate the keyboard shortcut. This enhances the user interface by making the shortcut more explicit and user-friendly.
Added a new `swapPanes` method in `window.ts` to swap locations of two panes. Modified key event handling in `pane.ts` to enable swapping panes when Shift is held and an arrow key is pressed. Removed debug logging and ensured dividers refresh in `layout.ts`.
Changed the rotate layout button icon from `arrow_2_circlepath` to `arrow_clockwise` for clarity. Additionally, implemented an event listener to rotate the active layout on button click, ensuring better user interaction.
Copy link

coderabbitai bot commented Oct 20, 2024

Walkthrough

The pull request introduces several enhancements to the terminal application, primarily focusing on user interface improvements and functionality. A new "Rotate active layout" button is added to the navigation bar in index.html, which triggers a layout change in the Terminal7 class. The Layout class is updated with a new method to dynamically change layout directions. Additionally, the Pane and Window classes receive modifications to improve keyboard event handling and pane management, respectively. These changes collectively enhance user interaction and layout management within the application.

Changes

File Change Summary
index.html Added "Rotate active layout" button with accessibility attributes; adjusted button formatting.
src/layout.ts Introduced changeDir method in Layout class for dynamic layout direction changes.
src/pane.ts Updated handleMetaKey for Shift key interactions; modified onChannelConnected, toggleZoom, and fit methods for improved functionality and error handling.
src/terminal7.ts Added event listener for "rotate-layout" button; modified loadChangelog to fetch and display content.
src/window.ts Introduced getPane, moveFocus, switchPane, and swapPanes methods for enhanced pane management.

Possibly related PRs

  • fixing reconnect #491: The changes in the main PR introduce a new button for "Rotate active layout" in the UI, which is directly related to the modifications in the Terminal7 class that handle the event listener for this button, allowing users to rotate the layout of the terminal interface.

🐰 In the terminal, I hop and play,
With buttons new to brighten the day.
Rotate the layout, left and right,
A bunny's joy in the user’s sight!
With each click, the panes align,
Hopping through code, all is fine! 🐇✨


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

netlify bot commented Oct 20, 2024

Deploy Preview for terminal7 ready!

Name Link
🔨 Latest commit d58d97c
🔍 Latest deploy log https://app.netlify.com/sites/terminal7/deploys/6714b8d7347e0b0008868f16
😎 Deploy Preview https://deploy-preview-496--terminal7.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

Copy link

netlify bot commented Oct 20, 2024

Deploy Preview for dazzling-kringle-090742 ready!

Name Link
🔨 Latest commit d58d97c
🔍 Latest deploy log https://app.netlify.com/sites/dazzling-kringle-090742/deploys/6714b8d75ff2ca0008789f29
😎 Deploy Preview https://deploy-preview-496--dazzling-kringle-090742.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify site configuration.

@daonb daonb self-requested a review October 20, 2024 08:03
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Outside diff range and nitpick comments (8)
index.html (1)

150-154: LGTM! Consider a minor improvement for consistency.

The changes look good and align with the PR objective of introducing a rotate panes feature. The new "Rotate active layout" button is well-integrated into the existing UI.

For consistency, consider applying the same inline rotation style to the "Split Right to Left" button icon:

- <button type="button" aria-label="Split Right to Left" data-sc="'" id="divide-h" class="pane-buttons off has-help"><i class="f7-icons">divide</i></button>
+ <button type="button" aria-label="Split Right to Left" data-sc="'" id="divide-h" class="pane-buttons off has-help">
+     <i class="f7-icons" style="display: inline-block;">divide</i>
+ </button>

This change would make all split buttons visually consistent.

src/terminal7.ts (3)

316-321: LGTM! Consider adding error handling.

The implementation of the rotate layout functionality looks good and aligns with the PR objective. It correctly checks for an active gate before attempting to rotate the layout.

Consider adding error handling to gracefully manage cases where this.activeG, this.activeG.activeW, or this.activeG.activeW.activeP might be undefined. For example:

 rotateLayout.addEventListener("click", () =>  {
-    if(this.activeG){
+    if(this.activeG?.activeW?.activeP){
         this.activeG.activeW.activeP.layout.changeDir()
+    } else {
+        console.warn("Unable to rotate layout: No active pane")
     }
 })

Line range hint 1022-1041: LGTM! Consider adding error handling.

The implementation of the loadChangelog method looks good. It effectively fetches and parses the changelog, and handles potential id conflicts and link behavior.

Consider adding error handling to manage potential issues during the fetch operation. For example:

 async loadChangelog() {
-    const resp = await fetch(changelogURL)
-    const changelog = await resp.text()
-    const e = document.getElementById("changelog-content")
-    e.innerHTML = marked.parse(changelog)
+    try {
+        const resp = await fetch(changelogURL)
+        if (!resp.ok) {
+            throw new Error(`HTTP error! status: ${resp.status}`)
+        }
+        const changelog = await resp.text()
+        const e = document.getElementById("changelog-content")
+        e.innerHTML = marked.parse(changelog)
+        // Rest of the method...
+    } catch (error) {
+        console.error("Failed to load changelog:", error)
+        // Optionally, update the UI to inform the user
+    }
 }

This change will help gracefully handle network errors or issues with the changelog URL.


Line range hint 1-1041: Resize functionality is present, but pane deletion logic is missing.

The resize functionality is implemented in src/webrtc_session.ts, but no corresponding pane deletion logic was found across the entire codebase. This means the reported bug regarding resizing issues after deleting panes in a mixed layout is not addressed.

Please implement pane deletion logic to ensure that panes are properly removed and that the layout resizes correctly afterward.

🔗 Analysis chain

Line range hint 1-1041: Changes look good, but the reported bug is not addressed.

The changes to add the rotate layout functionality and improve the changelog loading are well-implemented and integrated into the existing codebase. They align with the PR objective and don't introduce any apparent conflicts.

However, the bug mentioned in the PR description about resizing issues after deleting panes in a mixed layout is not addressed in this file. To verify if this issue is handled elsewhere, we can search for relevant code:

If the bug is not addressed in other files, it should be investigated and fixed before merging this PR.


Line range hint 1-51: Resize functionality is present, but pane deletion logic needs verification.

To ensure that the reported bug regarding resizing issues after deleting panes is addressed, we need to verify the pane deletion logic within src/webrtc_session.ts.


Line range hint 1-1041: Resize functionality is present, but pane deletion logic appears to be missing.

The previous search for pane deletion logic in src/webrtc_session.ts did not yield any results. This indicates that the reported bug regarding resizing issues after deleting panes is likely unaddressed.

To ensure comprehensive verification, we need to check the entire codebase for any pane deletion implementations.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for pane deletion and resizing logic
rg -n "delete.*pane|resize.*pane" --type ts

Length of output: 170


Script:

#!/bin/bash
# Search for pane deletion logic in webrtc_session.ts
rg -n "delete.*pane" src/webrtc_session.ts

Length of output: 44


Script:

#!/bin/bash
# Search for pane deletion logic across the entire TypeScript codebase
rg -n "delete.*pane" --type ts

Length of output: 32

src/window.ts (3)

Line range hint 185-216: Handle potential null reference when this.activeP is undefined in getPane method

In the getPane method, this.activeP is used without checking if it is null or undefined. If there is no active pane, accessing properties like this.activeP.t.buffer.active will cause a runtime error.

Consider adding a null check at the beginning of the method:

+        if (!this.activeP) {
+            return null;
+        }
         const a = this.activeP,
             b = a.t.buffer.active,
             x = a.xoff + b.cursorX * a.sx / a.t.cols,
             y = a.yoff + b.cursorY * a.sy / a.t.rows;

Line range hint 192-209: Ensure match function is defined to prevent runtime errors

If the where parameter does not match any of the expected cases ("left", "right", "up", "down"), the match function remains null. Calling match(c) when match is null will result in a runtime error.

Consider adding a default case or validating the where parameter:

             switch(where) {
                 case "left":
                     // existing code
                     break;
                 // other cases
+                default:
+                    console.warn(`Unrecognized direction: ${where}`);
+                    return null;
             }

Alternatively, you can check if match is defined before using it:

             // existing code
             this.t7.cells.forEach(c => {
                 if ((nextPane == null) && (c instanceof Pane)
                     && c.w && (c.w == this))
+                    if (match && match(c))
                         nextPane = c
             })

Line range hint 194-207: Define an epsilon constant for floating-point comparisons

Using the magic number 0.00001 for floating-point comparisons can reduce code readability. Defining it as a constant improves maintainability.

+        const EPSILON = 0.00001; // You could also use Number.EPSILON if appropriate
         switch(where) {
             case "left":
                 match = p => ((Math.abs(p.xoff + p.sx - a.xoff) < EPSILON)
                     && (p.yoff <= y) && (p.yoff+p.sy >= y))
                 break
             // other cases
         }
src/layout.ts (1)

373-373: Remove unnecessary console.log statements to clean up the code

There is an active console.log statement at line 373 and commented-out console.log statements at lines 390-395 and 407-412. Leaving debugging statements in production code can clutter the console output and may impact performance. It's good practice to remove or properly manage these statements before merging.

Apply this diff to remove the unnecessary logs:

-       console.log('origdir',this.dir)
...
-               // console.log('c',{
-               //     xoff: c.xoff,
-               //     yoff: c.yoff,
-               //     sx: c.sx,
-               //     sy: c.sy,
-               // })
...
-               // console.log('c2',{
-               //     xoff: c.xoff,
-               //     yoff: c.yoff,
-               //     sx: c.sx,
-               //     sy: c.sy,
-               // })

Also applies to: 390-395, 407-412

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 57180f3 and d58d97c.

📒 Files selected for processing (5)
  • index.html (1 hunks)
  • src/layout.ts (1 hunks)
  • src/pane.ts (1 hunks)
  • src/terminal7.ts (1 hunks)
  • src/window.ts (3 hunks)
🧰 Additional context used
🔇 Additional comments (1)
src/window.ts (1)

219-225: LGTM: moveFocus method correctly changes focus to the next pane

The moveFocus method properly obtains the next pane using getPane(where) and shifts focus if a pane is found.

Comment on lines +227 to +229
switchPane(where){
console.log(this.activeP)
}
Copy link

@coderabbitai coderabbitai bot Oct 20, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Implement functionality for switchPane method

The switchPane method currently only logs the active pane to the console. To fulfill its intended purpose, please implement the logic to switch or rotate panes.

Consider implementing the pane-switching logic or, if this is a placeholder, add a TODO comment to indicate future work:

        switchPane(where){
            // TODO: Implement pane-switching logic based on the 'where' parameter
            console.log(this.activeP);
        }

Copy link
Contributor

Choose a reason for hiding this comment

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

Good point

Copy link

Choose a reason for hiding this comment

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

@daonb, happy to help! Here's a possible implementation for the switchPane method that swaps the active pane with the pane in the specified direction:

switchPane(where: string) {
    const paneToSwap = this.getPane(where);
    if (paneToSwap) {
        this.swapPanes(this.activeP, paneToSwap);
        this.gate.sendState();
    } else {
        console.log(`No pane found in the direction: ${where}`);
    }
}

😊🐰

Comment on lines +288 to +302
const pane1Xoff = pane1.xoff
const pane1Yoff = pane1.yoff
const pane1Sx = pane1.sx
const pane1Sy = pane1.sy

pane1.xoff = pane2.xoff
pane1.yoff = pane2.yoff
pane1.sx = pane2.sx
pane1.sy = pane2.sy

pane2.xoff = pane1Xoff
pane2.yoff = pane1Yoff
pane2.sx = pane1Sx
pane2.sy = pane1Sy

Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Refactor property swapping to reduce code duplication

The swapping of xoff, yoff, sx, and sy properties between pane1 and pane2 can be made more concise.

Consider simplifying the code using array destructuring:

             // Swap position and size properties
-            const pane1Xoff = pane1.xoff
-            const pane1Yoff = pane1.yoff
-            const pane1Sx   = pane1.sx
-            const pane1Sy   = pane1.sy
-
-            pane1.xoff = pane2.xoff
-            pane1.yoff = pane2.yoff
-            pane1.sx = pane2.sx
-            pane1.sy = pane2.sy
-
-            pane2.xoff = pane1Xoff
-            pane2.yoff = pane1Yoff
-            pane2.sx = pane1Sx
-            pane2.sy = pane1Sy
+            [pane1.xoff, pane2.xoff] = [pane2.xoff, pane1.xoff];
+            [pane1.yoff, pane2.yoff] = [pane2.yoff, pane1.yoff];
+            [pane1.sx, pane2.sx] = [pane2.sx, pane1.sx];
+            [pane1.sy, pane2.sy] = [pane2.sy, pane1.sy];
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const pane1Xoff = pane1.xoff
const pane1Yoff = pane1.yoff
const pane1Sx = pane1.sx
const pane1Sy = pane1.sy
pane1.xoff = pane2.xoff
pane1.yoff = pane2.yoff
pane1.sx = pane2.sx
pane1.sy = pane2.sy
pane2.xoff = pane1Xoff
pane2.yoff = pane1Yoff
pane2.sx = pane1Sx
pane2.sy = pane1Sy
// Swap position and size properties
[pane1.xoff, pane2.xoff] = [pane2.xoff, pane1.xoff];
[pane1.yoff, pane2.yoff] = [pane2.yoff, pane1.yoff];
[pane1.sx, pane2.sx] = [pane2.sx, pane1.sx];
[pane1.sy, pane2.sy] = [pane2.sy, pane1.sy];

Comment on lines +278 to +305
swapPanes(pane1: Pane, pane2: Pane){
const pane1Layout = pane1.layout
const pane2Layout = pane2.layout
const pane1Index = pane1Layout.cells.indexOf(pane1);
const pane2Index = pane2Layout.cells.indexOf(pane2);
pane1Layout.cells[pane1Index] = pane2;
pane2Layout.cells[pane2Index] = pane1;
pane1.layout = pane2Layout;
pane2.layout = pane1Layout;

const pane1Xoff = pane1.xoff
const pane1Yoff = pane1.yoff
const pane1Sx = pane1.sx
const pane1Sy = pane1.sy

pane1.xoff = pane2.xoff
pane1.yoff = pane2.yoff
pane1.sx = pane2.sx
pane1.sy = pane2.sy

pane2.xoff = pane1Xoff
pane2.yoff = pane1Yoff
pane2.sx = pane1Sx
pane2.sy = pane1Sy

pane1Layout.refreshDividers();
pane2Layout.refreshDividers();
}
Copy link

@coderabbitai coderabbitai bot Oct 20, 2024

Choose a reason for hiding this comment

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

⚠️ Potential issue

Handle swapping panes within the same layout to prevent errors

The swapPanes method may encounter issues when pane1 and pane2 are within the same layout. Swapping them without checking can lead to incorrect indexing and behavior.

Add a condition to handle cases where panes share the same layout:

         swapPanes(pane1: Pane, pane2: Pane){
             const pane1Layout = pane1.layout
             const pane2Layout = pane2.layout
             const pane1Index = pane1Layout.cells.indexOf(pane1);
             const pane2Index = pane2Layout.cells.indexOf(pane2);
+            if (pane1Layout === pane2Layout) {
+                // Swap panes within the same layout
+                [pane1Layout.cells[pane1Index], pane1Layout.cells[pane2Index]] = [pane2, pane1];
+            } else {
                 pane1Layout.cells[pane1Index] = pane2;
                 pane2Layout.cells[pane2Index] = pane1;
+            }
             pane1.layout = pane2Layout;
             pane2.layout = pane1Layout;
             // Rest of the code remains the same
         }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
swapPanes(pane1: Pane, pane2: Pane){
const pane1Layout = pane1.layout
const pane2Layout = pane2.layout
const pane1Index = pane1Layout.cells.indexOf(pane1);
const pane2Index = pane2Layout.cells.indexOf(pane2);
pane1Layout.cells[pane1Index] = pane2;
pane2Layout.cells[pane2Index] = pane1;
pane1.layout = pane2Layout;
pane2.layout = pane1Layout;
const pane1Xoff = pane1.xoff
const pane1Yoff = pane1.yoff
const pane1Sx = pane1.sx
const pane1Sy = pane1.sy
pane1.xoff = pane2.xoff
pane1.yoff = pane2.yoff
pane1.sx = pane2.sx
pane1.sy = pane2.sy
pane2.xoff = pane1Xoff
pane2.yoff = pane1Yoff
pane2.sx = pane1Sx
pane2.sy = pane1Sy
pane1Layout.refreshDividers();
pane2Layout.refreshDividers();
}
swapPanes(pane1: Pane, pane2: Pane){
const pane1Layout = pane1.layout
const pane2Layout = pane2.layout
const pane1Index = pane1Layout.cells.indexOf(pane1);
const pane2Index = pane2Layout.cells.indexOf(pane2);
if (pane1Layout === pane2Layout) {
// Swap panes within the same layout
[pane1Layout.cells[pane1Index], pane1Layout.cells[pane2Index]] = [pane2, pane1];
} else {
pane1Layout.cells[pane1Index] = pane2;
pane2Layout.cells[pane2Index] = pane1;
}
pane1.layout = pane2Layout;
pane2.layout = pane1Layout;
const pane1Xoff = pane1.xoff
const pane1Yoff = pane1.yoff
const pane1Sx = pane1.sx
const pane1Sy = pane1.sy
pane1.xoff = pane2.xoff
pane1.yoff = pane2.yoff
pane1.sx = pane2.sx
pane1.sy = pane2.sy
pane2.xoff = pane1Xoff
pane2.yoff = pane1Yoff
pane2.sx = pane1Sx
pane2.sy = pane1Sy
pane1Layout.refreshDividers();
pane2Layout.refreshDividers();
}

Copy link
Contributor

Choose a reason for hiding this comment

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

I believe we assume both panes are of the same layout. It does make sense to check it.

Copy link

Choose a reason for hiding this comment

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

@daonb, understood. Noting that the code assumes both panes are within the same layout makes sense. Adding the check will help ensure proper handling.

(^_^)


✏️ Learnings added
Learnt from: daonb
PR: tuzig/terminal7#496
File: src/window.ts:278-305
Timestamp: 2024-10-21T15:24:31.289Z
Learning: In the `swapPanes` method in `src/window.ts`, it is assumed that both panes are within the same layout.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

Comment on lines +366 to +421
changeDir(){
if(this.dir === "TBD") return;
const parentDir = this.layout?.dir
const newDir = this.dir === 'rightleft' ? 'topbottom' : 'rightleft'
let keepXoff = false;
let keepYoff = false;
let cellSize;
console.log('origdir',this.dir)
if(this.dir === 'topbottom'){
keepYoff = true
cellSize = this.sy / this.cells.length
}else if(this.dir === 'rightleft') {
keepXoff = true
cellSize = this.sx / this.cells.length
}
this.cells.forEach((c, i) => {
const oldXoff = c.xoff
const oldYoff = c.yoff
const oldSx = c.sx;
const oldSy = c.sy;
c.yoff = oldXoff
c.xoff = oldYoff
c.sx = oldSy
c.sy = oldSx
// console.log('c',{
// xoff: c.xoff,
// yoff: c.yoff,
// sx: c.sx,
// sy: c.sy,
// })
if(keepYoff){
c.yoff = this.yoff + cellSize * i
c.xoff = this.xoff
c.sy = cellSize
c.sx = this.sx
}else if(keepXoff){
c.yoff = this.yoff
c.xoff = this.xoff + cellSize * i
c.sy = this.sy
c.sx = cellSize
}
// console.log('c2',{
// xoff: c.xoff,
// yoff: c.yoff,
// sx: c.sx,
// sy: c.sy,
// })
});
this.dir = newDir
this.refreshDividers()
if(this.dir === parentDir){
const replaceIndex = this.layout.cells.findIndex(c => c.id === this.id)
this.layout.cells.splice(replaceIndex, 1, ...this.cells)
this.layout.refreshDividers()
}
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Recommend adding unit tests for the new changeDir method

The changeDir method introduces significant new functionality that manipulates the layout of cells. To ensure correctness and prevent regressions, it's advisable to add unit tests covering various scenarios, such as:

  • Rotating layouts with different numbers of cells.
  • Handling nested layouts.
  • Verifying that cells retain expected properties after rotation.

Comment on lines +416 to +420
if(this.dir === parentDir){
const replaceIndex = this.layout.cells.findIndex(c => c.id === this.id)
this.layout.cells.splice(replaceIndex, 1, ...this.cells)
this.layout.refreshDividers()
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Prevent potential runtime error when this.layout is undefined

In the conditional block starting at line 416, accessing this.layout.cells without ensuring that this.layout is defined can lead to a TypeError if this.layout is undefined. This can occur when the current layout has no parent layout. To prevent this, add a null check for this.layout before accessing its properties.

Apply this diff to add a null check:

        this.dir = newDir
        this.refreshDividers()
-       if(this.dir === parentDir){
+       if(this.dir === parentDir && this.layout){
            const replaceIndex = this.layout.cells.findIndex(c => c.id === this.id)
            this.layout.cells.splice(replaceIndex, 1, ...this.cells)
            this.layout.refreshDividers()
        }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(this.dir === parentDir){
const replaceIndex = this.layout.cells.findIndex(c => c.id === this.id)
this.layout.cells.splice(replaceIndex, 1, ...this.cells)
this.layout.refreshDividers()
}
if(this.dir === parentDir && this.layout){
const replaceIndex = this.layout.cells.findIndex(c => c.id === this.id)
this.layout.cells.splice(replaceIndex, 1, ...this.cells)
this.layout.refreshDividers()
}

Comment on lines +566 to +568
if(ev.shiftKey){
this.layout.cells.forEach(c => console.log(c))
f = () => this.layout.changeDir()
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue

Remove debugging console.log statement in Shift+R handler

The console.log statement inside the Shift+R handler appears to be leftover debugging code. Removing it will clean up the console output in production.

Apply this diff to remove the unnecessary console.log call:

if (ev.shiftKey) {
-    this.layout.cells.forEach(c => console.log(c));
    f = () => this.layout.changeDir();
} else {
    f = () => this.gate.reset();
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ev.shiftKey){
this.layout.cells.forEach(c => console.log(c))
f = () => this.layout.changeDir()
if(ev.shiftKey){
f = () => this.layout.changeDir()

Comment on lines +578 to +584
if(ev.shiftKey){
const pane = this.w.getPane("left")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("left")
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Provide user feedback when no pane exists to swap with on Shift+ArrowLeft

When Shift+ArrowLeft is pressed and there is no pane to the left, the function returns silently. Consider notifying the user to improve the user experience.

Apply this diff to inform the user when no adjacent pane is available:

if (ev.shiftKey) {
    const pane = this.w.getPane("left");
    if (!pane) {
+       this.gate.notify("No pane to the left to swap with.");
        return;
    }
    this.w.swapPanes(this, pane);
} else {
    f = () => this.w.moveFocus("left");
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ev.shiftKey){
const pane = this.w.getPane("left")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("left")
}
if(ev.shiftKey){
const pane = this.w.getPane("left")
if(!pane) {
this.gate.notify("No pane to the left to swap with.");
return;
}
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("left")
}

Comment on lines +605 to +611
if(ev.shiftKey){
const pane = this.w.getPane("down")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("down")
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Provide user feedback when no pane exists to swap with on Shift+ArrowDown

When swapping panes downward, inform the user if there's no pane below.

Apply this diff:

if (ev.shiftKey) {
    const pane = this.w.getPane("down");
    if (!pane) {
+       this.gate.notify("No pane below to swap with.");
        return;
    }
    this.w.swapPanes(this, pane);
} else {
    f = () => this.w.moveFocus("down");
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ev.shiftKey){
const pane = this.w.getPane("down")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("down")
}
if(ev.shiftKey){
const pane = this.w.getPane("down")
if(!pane) {
this.gate.notify("No pane below to swap with.");
return;
}
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("down")
}

Comment on lines +587 to +593
if(ev.shiftKey){
const pane = this.w.getPane("right")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("right")
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Provide user feedback when no pane exists to swap with on Shift+ArrowRight

Similar to the left direction, inform the user when there's no pane to the right to swap with.

Apply this diff:

if (ev.shiftKey) {
    const pane = this.w.getPane("right");
    if (!pane) {
+       this.gate.notify("No pane to the right to swap with.");
        return;
    }
    this.w.swapPanes(this, pane);
} else {
    f = () => this.w.moveFocus("right");
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ev.shiftKey){
const pane = this.w.getPane("right")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("right")
}
if(ev.shiftKey){
const pane = this.w.getPane("right")
if(!pane) {
this.gate.notify("No pane to the right to swap with.");
return;
}
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("right")
}

Comment on lines +596 to +602
if(ev.shiftKey){
const pane = this.w.getPane("up")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("up")
}
Copy link

Choose a reason for hiding this comment

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

🛠️ Refactor suggestion

Provide user feedback when no pane exists to swap with on Shift+ArrowUp

When swapping panes upward, notify the user if no pane is available above.

Apply this diff:

if (ev.shiftKey) {
    const pane = this.w.getPane("up");
    if (!pane) {
+       this.gate.notify("No pane above to swap with.");
        return;
    }
    this.w.swapPanes(this, pane);
} else {
    f = () => this.w.moveFocus("up");
}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if(ev.shiftKey){
const pane = this.w.getPane("up")
if(!pane) return;
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("up")
}
if(ev.shiftKey){
const pane = this.w.getPane("up")
if(!pane) {
this.gate.notify("No pane above to swap with.");
return;
}
this.w.swapPanes(this,pane)
}else {
f = () => this.w.moveFocus("up")
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants