Chat: drag handle with detents (fit, 1/3, 1/2, full screen), chat width setting; tall transparent panel

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
maksarsanjeev
2026-10-06 22:19:27 +03:00
parent fbf90fd4fb
commit a4d5032959
5 changed files with 119 additions and 16 deletions
+28
View File
@@ -395,6 +395,33 @@ final class AppState: ObservableObject {
#endif
// Claude plan gauge (from statusline hook)
// MARK: Chat panel size (BroV)
// Detents: 0 = fits the messages (as before), 1 = ⅓ screen, 2 = ½ screen, 3 = full height.
@Published var chatDetent: Int = 0
/// Live height while the user drags the handle; nil otherwise.
@Published var chatDragHeight: CGFloat? = nil
@Published var chatWidth: CGFloat = 720 {
didSet { UserDefaults.standard.set(Double(chatWidth), forKey: "chatWidth") }
}
static let chatWidthOptions: [CGFloat] = [640, 720, 820, 960]
var screenHeight: CGFloat {
(IslandWindowController.notchScreen() ?? NSScreen.main)?.frame.height ?? 900
}
func chatDetentHeight(_ d: Int) -> CGFloat {
let auto = min(300, 240 + CGFloat(chatHistory.count) * 40)
switch d {
case 1: return max(320, screenHeight / 3)
case 2: return max(340, screenHeight / 2)
case 3: return screenHeight - 6
default: return auto
}
}
/// Current chat island height (drag, else detent).
var chatIslandHeight: CGFloat { chatDragHeight ?? chatDetentHeight(chatDetent) }
/// ChatGPT (Codex) weekly plan window, read from ~/.codex/sessions by CodexUsageMonitor.
@Published var codexWeekly: PlanWindow? = nil
@Published var claudePlanUsage: PlanUsage? = nil {
@@ -433,6 +460,7 @@ final class AppState: ObservableObject {
!v.trimmingCharacters(in: .whitespaces).isEmpty { claudeModel = v }
if let v = ud.string(forKey: "chatProvider"), let p = ChatProvider(rawValue: v) { chatProvider = p }
if let v = ud.string(forKey: "claudeCodeModel") { claudeCodeModel = v }
if let v = ud.object(forKey: "chatWidth") as? Double, v >= 560 { chatWidth = CGFloat(v) }
if let v = ud.string(forKey: "chatWorkingDirectory"), !v.isEmpty { chatWorkingDirectory = v }
if let v = ud.string(forKey: "claudeBinaryPath") { claudeBinaryPath = v }
if let v = ud.string(forKey: "claudePermissionMode"), !v.isEmpty { claudePermissionMode = v }