@@ -29,55 +29,144 @@ struct OutdatedPackagesList_Table: View
2929 }
3030 }
3131
32- /// Check whether all relevant packages are deselected
32+ var sortedRelevantPackages : [ OutdatedPackage ]
33+ {
34+ return relevantPackages. sorted ( by: { $0. package . installedOn! < $1. package . installedOn! } )
35+ }
36+
37+ var filteredRelevantPackages : [ OutdatedPackage ]
38+ {
39+ guard !searchText. isEmpty else
40+ {
41+ return sortedRelevantPackages
42+ }
43+
44+ return sortedRelevantPackages. filter ( { $0. package . name. localizedCaseInsensitiveContains ( searchText) } )
45+ }
46+
47+ /// Check whether all relevant packages are deselected - for `Deselect All` button
3348 var areAnyRelevantPackagesSelected : Bool
3449 {
3550 !relevantPackages. filter ( { $0. isMarkedForUpdating } ) . isEmpty
3651 }
3752
53+ /// Check if there is at least one package that is not selected - for `Select All` button
54+ var areAnyPackagesLeftToSelect : Bool
55+ {
56+ return relevantPackages. filter ( { !$0. isMarkedForUpdating } ) . isEmpty
57+ }
58+
59+ @State private var isShowingSearchField : Bool = false
60+
61+ @State private var searchText : String = " "
62+
3863 var body : some View
3964 {
40- Table ( of : OutdatedPackage . self )
65+ GroupBox
4166 {
42- TableColumn ( " start-page.updates.action " )
43- { outdatedPackage in
44- Toggle ( isOn: Bindable ( outdatedPackage) . isMarkedForUpdating) {
45- EmptyView ( )
67+ VStack ( spacing: 0 )
68+ {
69+ VStack ( spacing: 2 )
70+ {
71+ HStack ( alignment: . center)
72+ {
73+ selectAllButton ( packagesToSelect: relevantPackages)
74+
75+ deselectAllButton ( packagesToDeselect: relevantPackages)
76+
77+ Spacer ( )
78+
79+ ToggleSearchFieldButton ( isShowingSearchField: $isShowingSearchField)
80+ }
81+
82+ if isShowingSearchField
83+ {
84+ VStack ( spacing: 2 )
85+ {
86+ Divider ( )
87+
88+ CustomSearchField ( search: $searchText, customPromptText: nil )
89+ . animation ( . smooth, value: isShowingSearchField)
90+ }
91+ }
4692 }
93+ . padding ( [ . horizontal, . top] , 4 )
4794 }
48- . width ( 45 )
95+
96+ Table ( of: OutdatedPackage . self)
97+ {
98+ TableColumn ( " start-page.updates.action " )
99+ { outdatedPackage in
100+ Toggle ( isOn: Bindable ( outdatedPackage) . isMarkedForUpdating) {
101+ EmptyView ( )
102+ }
103+ }
104+ . width ( 45 )
49105
50- TableColumn ( " package-details.dependencies.results.name " , value: \. package . name)
106+ TableColumn ( " package-details.dependencies.results.name " , value: \. package . name)
51107
52- TableColumn ( " start-page.updates.installed-version " )
53- { outdatedPackage in
54- Text ( outdatedPackage. installedVersions. formatted ( . list( type: . and) ) )
55- }
108+ TableColumn ( " start-page.updates.installed-version " )
109+ { outdatedPackage in
110+ Text ( outdatedPackage. installedVersions. formatted ( . list( type: . and) ) )
111+ }
56112
57- TableColumn ( " start-page.updates.newest-version " )
58- { outdatedPackage in
59- Text ( outdatedPackage. newerVersion)
60- }
113+ TableColumn ( " start-page.updates.newest-version " )
114+ { outdatedPackage in
115+ Text ( outdatedPackage. newerVersion)
116+ }
61117
62- TableColumn ( " package-details.type " )
63- { outdatedPackage in
64- Text ( outdatedPackage. package . type. description)
65- }
118+ TableColumn ( " package-details.type " )
119+ { outdatedPackage in
120+ Text ( outdatedPackage. package . type. description)
121+ }
66122
67- } rows: {
68- ForEach ( relevantPackages. sorted ( by: { $0. package . installedOn! < $1. package . installedOn! } ) )
69- { outdatedPackage in
70- TableRow ( outdatedPackage)
71- . contextMenu
72- {
73- PreviewPackageButton ( packageToPreview: . init(
74- name: outdatedPackage. package . name,
75- type: outdatedPackage. package . type,
76- installedIntentionally: outdatedPackage. package . installedIntentionally)
77- )
78- }
123+ } rows: {
124+ ForEach ( filteredRelevantPackages)
125+ { outdatedPackage in
126+ TableRow ( outdatedPackage)
127+ . contextMenu
128+ {
129+ PreviewPackageButton ( packageToPreview: . init(
130+ name: outdatedPackage. package . name,
131+ type: outdatedPackage. package . type,
132+ installedIntentionally: outdatedPackage. package . installedIntentionally)
133+ )
134+ }
135+ }
136+ }
137+ . tableStyle ( . bordered)
138+ }
139+ }
140+
141+ @ViewBuilder
142+ func selectAllButton( packagesToSelect: Set < OutdatedPackage > ) -> some View
143+ {
144+ Button
145+ {
146+ relevantPackages. forEach
147+ {
148+ $0. changeMarkedState ( to: true )
149+ }
150+ } label: {
151+ Text ( " start-page.updated.action.select-all " )
152+ }
153+ . disabled ( areAnyPackagesLeftToSelect)
154+ . buttonStyle ( . accessoryBar)
155+ }
156+
157+ @ViewBuilder
158+ func deselectAllButton( packagesToDeselect: Set < OutdatedPackage > ) -> some View
159+ {
160+ Button
161+ {
162+ relevantPackages. forEach
163+ {
164+ $0. changeMarkedState ( to: false )
79165 }
166+ } label: {
167+ Text ( " start-page.updated.action.deselect-all " )
80168 }
81- . tableStyle ( . bordered)
169+ . disabled ( !areAnyRelevantPackagesSelected)
170+ . buttonStyle ( . accessoryBar)
82171 }
83172}
0 commit comments