33// TablePro
44//
55
6- import AppKit
76import os
87import SwiftUI
98import UniformTypeIdentifiers
109
1110struct WelcomeWindowView : View {
1211 private enum FocusField {
13- case search
1412 case connectionList
1513 }
1614
@@ -35,11 +33,9 @@ struct WelcomeWindowView: View {
3533 . transition ( . move( edge: . trailing) )
3634 }
3735 }
38- . background ( VisualEffectBackground ( material: . underWindowBackground, blendingMode: . behindWindow) )
39- . ignoresSafeArea ( )
4036 . onAppear {
4137 vm. setUp ( )
42- focus = . search
38+ focus = . connectionList
4339 }
4440 . alert (
4541 vm. connectionsToDelete. count == 1
@@ -199,104 +195,60 @@ struct WelcomeWindowView: View {
199195 // MARK: - Layout
200196
201197 private var welcomeContent : some View {
202- HStack ( spacing : 0 ) {
198+ NavigationSplitView ( columnVisibility : . constant ( . all ) ) {
203199 WelcomeLeftPanel (
204200 onActivateLicense: { vm. activeSheet = . activation } ,
205201 onCreateConnection: { WindowOpener . shared. openConnectionForm ( ) }
206202 )
207- Divider ( )
208- rightPanel
203+ . navigationSplitViewColumnWidth ( 240 )
204+ . toolbar ( removing: . sidebarToggle)
205+ } detail: {
206+ connectionsDetail
209207 }
208+ . navigationSplitViewStyle ( . balanced)
210209 . transition ( . opacity)
211210 }
212211
213- // MARK: - Right Panel
214-
215- private var rightPanel : some View {
216- VStack ( spacing: 0 ) {
217- HStack ( spacing: 0 ) {
218- HStack ( spacing: 4 ) {
219- WelcomeToolbarButton (
220- systemImage: " plus " ,
221- help: String ( localized: " New Connection (⌘N) " ) ,
222- accessibilityLabel: String ( localized: " New Connection " )
223- ) {
224- WindowOpener . shared. openConnectionForm ( )
225- }
226-
227- WelcomeToolbarButton (
228- systemImage: " folder.badge.plus " ,
229- help: String ( localized: " New Group " ) ,
230- accessibilityLabel: String ( localized: " New Group " )
231- ) {
232- vm. pendingMoveToNewGroup = [ ]
233- vm. activeSheet = . newGroup( parentId: nil )
234- }
235- }
236- . padding ( . trailing, 12 )
237-
238- NativeSearchField (
239- text: $vm. searchText,
240- placeholder: String ( localized: " Search for connection... " ) ,
241- controlSize: . regular
242- )
243- . focused ( $focus, equals: . search)
244- . onKeyPress ( . return) {
245- vm. connectSelectedConnections ( )
246- return . handled
247- }
248- . onKeyPress ( . escape) {
249- if !vm. searchText. isEmpty {
250- vm. searchText = " "
251- }
252- focus = . connectionList
253- return . handled
254- }
255- . onKeyPress ( characters: . init( charactersIn: " \u{7F} \u{08} " ) , phases: . down) { keyPress in
256- guard keyPress. modifiers. contains ( . command) else { return . ignored }
257- let toDelete = vm. selectedConnections
258- guard !toDelete. isEmpty else { return . ignored }
259- vm. connectionsToDelete = toDelete
260- vm. showDeleteConfirmation = true
261- return . handled
262- }
263- . onKeyPress ( characters: . init( charactersIn: " jn " ) , phases: [ . down, . repeat ] ) { keyPress in
264- guard keyPress. modifiers. contains ( . control) else { return . ignored }
265- vm. moveToNextConnection ( )
266- focus = . connectionList
267- return . handled
268- }
269- . onKeyPress ( characters: . init( charactersIn: " kp " ) , phases: [ . down, . repeat ] ) { keyPress in
270- guard keyPress. modifiers. contains ( . control) else { return . ignored }
271- vm. moveToPreviousConnection ( )
272- focus = . connectionList
273- return . handled
274- }
275- . onKeyPress ( . downArrow) {
276- vm. moveToNextConnection ( )
277- focus = . connectionList
278- return . handled
279- }
280- . onKeyPress ( . upArrow) {
281- vm. moveToPreviousConnection ( )
282- focus = . connectionList
283- return . handled
284- }
285- }
286- . padding ( . horizontal, 16 )
287- . padding ( . vertical, 12 )
288-
289- Divider ( )
212+ // MARK: - Detail (Connections)
290213
214+ private var connectionsDetail : some View {
215+ Group {
291216 if vm. treeItems. isEmpty && vm. filteredConnections. isEmpty {
292217 emptyState
293218 } else {
294219 connectionList
295220 }
296221 }
297- . frame ( minWidth: 350 )
298222 . contentShape ( Rectangle ( ) )
299223 . contextMenu { newConnectionContextMenu }
224+ . searchable (
225+ text: $vm. searchText,
226+ placement: . toolbar,
227+ prompt: Text ( " Search for connection... " )
228+ )
229+ . onSubmit ( of: . search) {
230+ vm. connectSelectedConnections ( )
231+ }
232+ . toolbar {
233+ ToolbarItem ( placement: . primaryAction) {
234+ Button {
235+ WindowOpener . shared. openConnectionForm ( )
236+ } label: {
237+ Label ( String ( localized: " New Connection " ) , systemImage: " plus " )
238+ }
239+ . help ( String ( localized: " New Connection (⌘N) " ) )
240+ }
241+
242+ ToolbarItem ( placement: . primaryAction) {
243+ Button {
244+ vm. pendingMoveToNewGroup = [ ]
245+ vm. activeSheet = . newGroup( parentId: nil )
246+ } label: {
247+ Label ( String ( localized: " New Group " ) , systemImage: " folder.badge.plus " )
248+ }
249+ . help ( String ( localized: " New Group " ) )
250+ }
251+ }
300252 }
301253
302254 // MARK: - Connection List
@@ -667,47 +619,6 @@ private struct ConnectionCreationOverlays: ViewModifier {
667619 }
668620}
669621
670- // MARK: - Visual Effect Background
671-
672- private struct VisualEffectBackground : NSViewRepresentable {
673- let material : NSVisualEffectView . Material
674- let blendingMode : NSVisualEffectView . BlendingMode
675-
676- func makeNSView( context: Context ) -> NSVisualEffectView {
677- let view = NSVisualEffectView ( )
678- view. material = material
679- view. blendingMode = blendingMode
680- view. state = . followsWindowActiveState
681- view. isEmphasized = true
682- return view
683- }
684-
685- func updateNSView( _ view: NSVisualEffectView , context: Context ) {
686- view. material = material
687- view. blendingMode = blendingMode
688- }
689- }
690-
691- // MARK: - Toolbar Button
692-
693- private struct WelcomeToolbarButton : View {
694- let systemImage : String
695- let help : String
696- let accessibilityLabel : String
697- let action : ( ) -> Void
698-
699- var body : some View {
700- Button ( action: action) {
701- Image ( systemName: systemImage)
702- . frame ( width: 16 , height: 16 )
703- }
704- . buttonStyle ( . bordered)
705- . controlSize ( . large)
706- . help ( help)
707- . accessibilityLabel ( accessibilityLabel)
708- }
709- }
710-
711622// MARK: - Preview
712623
713624#Preview( " Welcome Window " ) {
0 commit comments