Skip to content

Conversation

@olivermrose
Copy link
Collaborator

@olivermrose olivermrose commented Dec 8, 2025

Splits allow multiple chats to be viewed at once. A multitude of new settings have been added to control the behavior of splits to make sure UX can be tailored. I set defaults to what I believe is most intuitive.

A couple of keyboard shortcuts have also been added:

  • Ctrl/Cmd+T will add a new split
  • Ctrl/Cmd+W will close the focused split

As well as new channel menu items.

Internally, splits are represented as a binary tree (never thought I'd see the day). Because splits can be arranged horizontally and vertically, I named the branches before and after to avoid confusion with the spatial representations of left and right.

Closes #15

@olivermrose olivermrose marked this pull request as ready for review December 11, 2025 03:17
Copilot AI review requested due to automatic review settings December 11, 2025 03:17
Copy link

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

This PR implements a comprehensive split view feature that allows users to view multiple Twitch chats simultaneously. The implementation uses a binary tree structure to manage split layouts with configurable behavior through new settings. Key features include drag-and-drop split management, keyboard shortcuts for split operations (Ctrl/Cmd+T to add, Ctrl/Cmd+W to close), and persistent layout restoration.

Key Changes:

  • Binary tree-based split layout system with horizontal/vertical panes
  • Five new settings controlling split behavior (orientation, restore, close, and auto-leave options)
  • Keyboard navigation between splits and keyboard shortcuts for split management
  • Drag-and-drop support for reordering and rearranging splits
  • Layout persistence across application restarts

Reviewed changes

Copilot reviewed 29 out of 30 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
src/lib/split-layout.ts Core split layout management class implementing binary tree operations, navigation, and drag-drop handling
src/routes/(main)/channels/split/SplitView.svelte Individual split view component with drag-drop zones and empty state
src/routes/(main)/channels/split/SplitNode.svelte Recursive component rendering split tree with resizable panes
src/routes/(main)/channels/split/SplitHeader.svelte Split header with controls for adding splits and closing
src/routes/(main)/channels/split/+page.svelte Main split page with keyboard navigation between splits
src/routes/settings/categories/splits.ts Settings definitions for split behavior configuration
src/lib/settings.ts Added split-related settings types and default values
src/lib/stores.ts New layout store for persisting split state
src/routes/(main)/channels/+layout.svelte Keyboard shortcuts for split operations (Ctrl/Cmd+T and Ctrl/Cmd+W)
src/routes/(main)/+layout.svelte DragDropProvider setup and drag overlay component
src/routes/(main)/+page.svelte Layout restoration logic on app startup
src/lib/components/Channel.svelte Extracted channel view component for reuse in splits
src/lib/menus/channel-menu.ts Added split-related menu items for opening and arranging channels
src/lib/components/DraggableChannel.svelte New draggable wrapper for channel list items
src/lib/models/channel.svelte.ts Added split parameter to join method
package.json & pnpm-lock.yaml Added paneforge dependency for resizable panes
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +18 to +30
<Pane defaultSize={node.size ?? 50} onResize={(size) => (node.size = size)}>
<Self bind:node={node.before} />
</Pane>

<PaneResizer
class={[
"bg-muted relative flex items-center justify-center transition-colors hover:bg-blue-400",
node.axis === "horizontal" ? "w-1 cursor-col-resize" : "h-1 cursor-row-resize",
]}
/>

<Pane defaultSize={100 - (node.size ?? 50)} onResize={(size) => (node.size = 100 - size)}>
<Self bind:node={node.after} />
Copy link

Copilot AI Dec 11, 2025

Choose a reason for hiding this comment

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

The onResize callbacks directly mutate the node.size property. Since node is passed as a bindable prop, this could cause reactivity issues or infinite update loops in Svelte 5. Additionally, the calculation 100 - size for the second pane assumes the first pane's new size, but if the sizes don't sum to 100 due to rounding or precision issues, this could cause layout inconsistencies. Consider validating that the sizes remain synchronized or handle the resize state more carefully.

Copilot uses AI. Check for mistakes.
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.

Splits

2 participants