From 22acaa90ca9a2481476ad71e691a4e1bad6a1230 Mon Sep 17 00:00:00 2001 From: Kaede Akino Date: Sat, 29 Aug 2026 10:30:40 +0800 Subject: [PATCH] Polish macOS theme integration --- Termind/Design/TerminalTheme.swift | 4 +- Termind/Features/SFTP/SFTPBrowserView.swift | 82 +++++++++---------- .../Workspaces/WorkspaceContentView.swift | 2 +- .../Components/SSHConnectionJourneyView.swift | 15 +--- TermindTests/TerminalThemeTests.swift | 6 ++ 5 files changed, 53 insertions(+), 56 deletions(-) diff --git a/Termind/Design/TerminalTheme.swift b/Termind/Design/TerminalTheme.swift index 2590c553..55f292a6 100644 --- a/Termind/Design/TerminalTheme.swift +++ b/Termind/Design/TerminalTheme.swift @@ -53,7 +53,7 @@ nonisolated struct TerminalTheme: Identifiable, Hashable, Sendable { static let termindDark = TerminalTheme( name: SettingsKey.defaultTerminalThemeDark, isDark: true, - background: RGB(0x11141A), + background: RGB(0x1E1E1E), foreground: RGB(0xD3D8E0), cursor: RGB(0x4B8BF5), selection: RGB(0x2A3550), @@ -68,7 +68,7 @@ nonisolated struct TerminalTheme: Identifiable, Hashable, Sendable { static let termindLight = TerminalTheme( name: SettingsKey.defaultTerminalThemeLight, isDark: false, - background: RGB(0xFBFBFD), + background: RGB(0xFFFFFF), foreground: RGB(0x2B303B), cursor: RGB(0x2C6BD8), selection: RGB(0xCFDDF7), diff --git a/Termind/Features/SFTP/SFTPBrowserView.swift b/Termind/Features/SFTP/SFTPBrowserView.swift index 5409d150..c93da2dd 100644 --- a/Termind/Features/SFTP/SFTPBrowserView.swift +++ b/Termind/Features/SFTP/SFTPBrowserView.swift @@ -291,7 +291,12 @@ struct SFTPBrowserView: View { @Bindable var sftpSession = sftpSession return ZStack { VStack(spacing: 0) { - pathBar(layout: layout) + VStack(spacing: 0) { + pathBar(layout: layout) + columnHeader(layout: layout) + } + .background(.background) + browserContent(layout: layout) } @@ -466,7 +471,6 @@ struct SFTPBrowserView: View { .frame(height: 48) } .buttonStyle(.plain) - .background(.background) .onChange(of: pathFocused) { wasFocused, isFocused in guard wasFocused, !isFocused, editsPath else { return } cancelPathEditing() @@ -678,41 +682,37 @@ struct SFTPBrowserView: View { } private func fileList(layout: Layout) -> some View { - VStack(spacing: 0) { - columnHeader(layout: layout) - - SFTPFileNativeList( - items: fileListItems(layout: layout), - scrollRequest: fileScrollRequest, - onBackgroundClick: clearFileSelection - ) { item in - fileRow(item.row, layout: layout) - } - .focusable(!window.isToolbarFindFocused) - .focusEffectDisabled() - .focused($listFocused) - .onKeyPress(.upArrow) { - moveSelection( - by: -1, extending: NSEvent.modifierFlags.contains(.shift) - ) - } - .onKeyPress(.downArrow) { - moveSelection( - by: 1, extending: NSEvent.modifierFlags.contains(.shift) - ) - } - .onKeyPress(.return) { - guard let file = keyboardTarget else { return .ignored } - primaryAction(file) - return .handled - } - .onKeyPress("a", phases: .down) { press in - guard press.modifiers.contains(.command) else { return .ignored } - sftpSession.selection = Set(sftpSession.filteredFiles.map(\.id)) - selectionAnchor = sftpSession.filteredFiles.first?.id - selectionCursor = sftpSession.filteredFiles.last?.id - return .handled - } + SFTPFileNativeList( + items: fileListItems(layout: layout), + scrollRequest: fileScrollRequest, + onBackgroundClick: clearFileSelection + ) { item in + fileRow(item.row, layout: layout) + } + .focusable(!window.isToolbarFindFocused) + .focusEffectDisabled() + .focused($listFocused) + .onKeyPress(.upArrow) { + moveSelection( + by: -1, extending: NSEvent.modifierFlags.contains(.shift) + ) + } + .onKeyPress(.downArrow) { + moveSelection( + by: 1, extending: NSEvent.modifierFlags.contains(.shift) + ) + } + .onKeyPress(.return) { + guard let file = keyboardTarget else { return .ignored } + primaryAction(file) + return .handled + } + .onKeyPress("a", phases: .down) { press in + guard press.modifiers.contains(.command) else { return .ignored } + sftpSession.selection = Set(sftpSession.filteredFiles.map(\.id)) + selectionAnchor = sftpSession.filteredFiles.first?.id + selectionCursor = sftpSession.filteredFiles.last?.id + return .handled } .background(.background) } @@ -776,19 +776,19 @@ struct SFTPBrowserView: View { .padding(.leading, Metrics.Space.xxl) .padding(.trailing, Metrics.Space.xl) .frame(height: 40) - .termindGlassBar() .overlay(alignment: .bottom) { Divider().opacity(0.7) } } private func sortHeader( _ title: LocalizedStringKey, field: SFTPFileSortField, separated: Bool = false ) -> some View { - Button { + let isSorted = sftpSession.sortField == field + return Button { sftpSession.sort(by: field) } label: { HStack(spacing: Metrics.Space.s) { - Text(title).font(.body.weight(.semibold)) - if sftpSession.sortField == field { + Text(title).font(.body.weight(isSorted ? .semibold : .regular)) + if isSorted { Image( systemName: sftpSession.sortDirection == .ascending ? "chevron.up" : "chevron.down" diff --git a/Termind/Features/Workspaces/WorkspaceContentView.swift b/Termind/Features/Workspaces/WorkspaceContentView.swift index 33c603f0..b979deb8 100644 --- a/Termind/Features/Workspaces/WorkspaceContentView.swift +++ b/Termind/Features/Workspaces/WorkspaceContentView.swift @@ -604,7 +604,7 @@ private struct PaneView: View { private var header: some View { if presentsConnectionJourney { headerContent.background { - SSHConnectionJourneyBackground(center: .bottomLeading) + SSHConnectionJourneyBackground() } } else if pane.kind == .sshSession { headerContent.background(terminalAppearance.background) diff --git a/Termind/UI/Components/SSHConnectionJourneyView.swift b/Termind/UI/Components/SSHConnectionJourneyView.swift index ee74e014..49916834 100644 --- a/Termind/UI/Components/SSHConnectionJourneyView.swift +++ b/Termind/UI/Components/SSHConnectionJourneyView.swift @@ -414,20 +414,10 @@ nonisolated private struct ConnectionLogListItem: Identifiable, Hashable, Sendab let message: String } -/// The continuous surface shared by a connection journey and its pane header. -/// The two instances anchor their glow to the adjoining edge, so they meet -/// without a color seam while retaining the Journey's subtle accent wash. +/// The system window surface shared by a connection journey and its pane header. struct SSHConnectionJourneyBackground: View { - var center: UnitPoint = .topLeading - var body: some View { - ZStack { - Color(nsColor: .windowBackgroundColor) - RadialGradient( - colors: [Color.accentColor.opacity(0.055), .clear], - center: center, startRadius: 20, endRadius: 520 - ) - } + Color(nsColor: .windowBackgroundColor) } } @@ -503,6 +493,7 @@ private struct ConnectionLogNativeList: NSViewRepresentable { guard let renderer else { return nil } return AnyView( renderer(item) + .frame(maxWidth: .infinity, alignment: .leading) .padding(.horizontal, 14) .environment(\.locale, locale) .environment(\.colorScheme, colorScheme) diff --git a/TermindTests/TerminalThemeTests.swift b/TermindTests/TerminalThemeTests.swift index 679007a1..09cf15d8 100644 --- a/TermindTests/TerminalThemeTests.swift +++ b/TermindTests/TerminalThemeTests.swift @@ -3,6 +3,12 @@ import Testing @testable import Termind struct TerminalThemeTests { + @Test + func defaultThemeBackgroundsMatchMacOSWindowBackgrounds() { + #expect(TerminalTheme.termindLight.background.hex == "FFFFFF") + #expect(TerminalTheme.termindDark.background.hex == "1E1E1E") + } + @Test func unavailableThemesFallBackForBothAppearances() { let light = TermindTerminalThemeCatalog.background(