Skip to content

Commit 5fe54fa

Browse files
committed
~ More work on the install process
1 parent 5a48dfe commit 5fe54fa

15 files changed

Lines changed: 202 additions & 93 deletions

File tree

Cork/Localizable.xcstrings

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17430,6 +17430,10 @@
1743017430
}
1743117431
}
1743217432
},
17433+
"add-package.top-packages.list-item-%@" : {
17434+
"comment" : "A label that shows the number of downloads for a package. The argument is the number of downloads.",
17435+
"isCommentAutoGenerated" : true
17436+
},
1743317437
"add-package.top-packages.list-item-%lld" : {
1743417438
"extractionState" : "manual",
1743517439
"localizations" : {
@@ -27650,6 +27654,10 @@
2765027654
},
2765127655
"cleaningUp" : {
2765227656

27657+
},
27658+
"DEBUG: Hello" : {
27659+
"comment" : "A description of the download count of a package.",
27660+
"isCommentAutoGenerated" : true
2765327661
},
2765427662
"DEBUG: Log packages to be adopted" : {
2765527663
"localizations" : {

Cork/Logic/App Intents/Currently Installed Packages/Get Installed Formulae Intent.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ struct GetInstalledFormulaeIntent: AppIntent
6868

6969
if getOnlyManuallyInstalledPackages
7070
{
71-
minimalPackages = minimalPackages.filter({ $0.installedIntentionally })
71+
minimalPackages = minimalPackages.filter({ $0.installedIntentionally ?? false })
7272
}
7373

7474
return .result(value: minimalPackages)

Cork/Views/Installation/Reusables/Search Result Row.swift

Lines changed: 31 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -17,50 +17,58 @@ struct SearchResultRow: View, Sendable
1717

1818
@Environment(BrewPackagesTracker.self) var brewPackagesTracker: BrewPackagesTracker
1919
@Environment(TopPackagesTracker.self) var topPackagesTracker: TopPackagesTracker
20-
21-
let searchedForPackage: MinimalHomebrewPackage
20+
2221
let context: Self.Context
2322

2423
@State private var description: String?
2524
@State private var isCompatible: Bool?
2625

2726
@State private var isLoadingDescription: Bool = true
2827
@State private var descriptionParsingFailed: Bool = false
28+
29+
/// Get the relevant package from the context
30+
var relevantPackage: MinimalHomebrewPackage
31+
{
32+
switch self.context
33+
{
34+
case .topPackage(let package, _):
35+
return package
36+
case .searchResult(let searchedForPackage):
37+
return searchedForPackage
38+
}
39+
}
2940

3041
var body: some View
3142
{
3243
VStack(alignment: .leading)
3344
{
3445
HStack(alignment: .center)
3546
{
36-
searchedForPackage.nameView(withComponents: .boundVersion)
47+
relevantPackage.nameView(withComponents: .boundVersion)
3748

3849
switch context
3950
{
40-
case .topPackages:
51+
case .topPackage(_, let downloadCount):
4152
Spacer()
4253

43-
// TODO: Reimplement download counts
44-
/*
45-
if let downloadCount = searchedForPackage.downloadCount
54+
if let downloadCount
4655
{
4756
Text("add-package.top-packages.list-item-\(downloadCount)")
4857
.foregroundStyle(.secondary)
4958
.font(.caption)
5059
}
51-
*/
52-
53-
case .searchResults:
54-
if searchedForPackage.type == .formula
60+
61+
case .searchResult(let package):
62+
if package.type == .formula
5563
{
56-
if brewPackagesTracker.successfullyLoadedFormulae.contains(where: { $0.getCompletePackageName() == searchedForPackage.internalName })
64+
if brewPackagesTracker.successfullyLoadedFormulae.contains(where: { $0.getCompletePackageName() == package.internalName })
5765
{
5866
PillTextWithLocalizableText(localizedText: "add-package.result.already-installed")
5967
}
6068
}
6169
else
6270
{
63-
if brewPackagesTracker.successfullyLoadedCasks.contains(where: { $0.getCompletePackageName() == searchedForPackage.internalName })
71+
if brewPackagesTracker.successfullyLoadedCasks.contains(where: { $0.getCompletePackageName() == package.internalName })
6472
{
6573
PillTextWithLocalizableText(localizedText: "add-package.result.already-installed")
6674
}
@@ -113,12 +121,12 @@ struct SearchResultRow: View, Sendable
113121
}
114122
}
115123
}
116-
.tag(searchedForPackage)
124+
.tag(relevantPackage)
117125
.task
118126
{
119127
if showDescriptionsInSearchResults
120128
{
121-
AppConstants.shared.logger.info("\(searchedForPackage.name(withPrecision: .precise), privacy: .auto) came into view")
129+
AppConstants.shared.logger.info("\(relevantPackage.name(withPrecision: .precise), privacy: .auto) came into view")
122130

123131
if description == nil
124132
{
@@ -127,11 +135,11 @@ struct SearchResultRow: View, Sendable
127135
isLoadingDescription = false
128136
}
129137

130-
AppConstants.shared.logger.info("\(searchedForPackage.name(withPrecision: .precise), privacy: .auto) does not have its description loaded")
138+
AppConstants.shared.logger.info("\(relevantPackage.name(withPrecision: .precise), privacy: .auto) does not have its description loaded")
131139

132140
do
133141
{
134-
guard let searchedForPackageConvertedForDetailLoading: BrewPackage = .init(using: searchedForPackage) else
142+
guard let searchedForPackageConvertedForDetailLoading: BrewPackage = .init(using: relevantPackage) else
135143
{
136144
AppConstants.shared.logger.error("Failed to convert minimal package to actual package")
137145

@@ -156,14 +164,17 @@ struct SearchResultRow: View, Sendable
156164
}
157165
else
158166
{
159-
AppConstants.shared.logger.info("\(searchedForPackage.name(withPrecision: .precise), privacy: .auto) already has its description loaded")
167+
AppConstants.shared.logger.info("\(relevantPackage.name(withPrecision: .precise), privacy: .auto) already has its description loaded")
160168
}
161169
}
162170
}
163171
}
164172

165173
enum Context {
166-
case searchResults
167-
case topPackages
174+
case searchResult(searchedForPackage: MinimalHomebrewPackage)
175+
case topPackage(
176+
package: MinimalHomebrewPackage,
177+
downloadCount: Int?
178+
)
168179
}
169180
}

Cork/Views/Installation/Sub-Views/Initial/Top Packages Section.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ struct TopPackagesSection: View
4848

4949
let convertedPackage: MinimalHomebrewPackage = .init(fromFullPackage: topPackage)
5050

51-
SearchResultRow(searchedForPackage: convertedPackage, context: .topPackages)
51+
SearchResultRow(context: .topPackage(package: convertedPackage, downloadCount: topPackage.downloadCount))
5252
}
5353
}
5454
} header: {

Cork/Views/Installation/Sub-Views/Installing.swift

Lines changed: 24 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -26,46 +26,53 @@ struct InstallingPackageView: View
2626

2727
@State var isShowingRealTimeOutput: Bool = false
2828

29-
@State private var installationProgressTracker: InstallationProgressTracker?
29+
@State private var installationProgressTracker: InstallationProgressTracker
30+
31+
init(packageToInstall: MinimalHomebrewPackage)
32+
{
33+
self.packageToInstall = packageToInstall
34+
self._installationProgressTracker = State(
35+
initialValue: InstallationProgressTracker(packageToInstall: packageToInstall)
36+
)
37+
}
3038

3139
var body: some View
3240
{
3341
VStack(alignment: .leading)
3442
{
35-
if let installationProgressTracker
43+
ProgressView(installationProgressTracker.installProgress)
44+
45+
switch installationProgressTracker.installStage
3646
{
37-
ProgressView(installationProgressTracker.installProgress)
38-
39-
switch installationProgressTracker.installStage
40-
{
41-
case .formula(let standardCases):
42-
Text(standardCases.stageDescription)
43-
case .cask(let standardCases):
44-
standardCases.view([packageToInstall])
45-
}
46-
47-
installationProgressTracker.streamedOutputsDisplay
47+
case .formula(let standardCases):
48+
Text(standardCases.stageDescription)
49+
case .cask(let standardCases):
50+
standardCases.view([packageToInstall])
4851
}
52+
53+
installationProgressTracker.streamedOutputsDisplay
4954
}
5055
.task
5156
{
52-
installationProgressTracker = .init(packageToInstall: packageToInstall)
53-
5457
do throws(InstallationProgressTracker.InstallationError)
5558
{
56-
try await installationProgressTracker!.installPackage(
59+
try await installationProgressTracker.installPackage(
5760
packageToInstall,
5861
using: brewPackagesTracker,
5962
cachedDownloadsTracker: cachedDownloadsTracker
6063
)
64+
65+
packageInstallationProcessStepTracker.advanceStep(to: .finished)
6166
} catch let installationError
6267
{
6368
switch installationError
6469
{
6570
case .implemented(let implementedError):
6671
packageInstallationProcessStepTracker.advanceStep(to: .erroredOut(withError: implementedError))
6772
case .unimplemented(let rawOutput):
68-
packageInstallationProcessStepTracker.advanceStep(to: .unexpectedTerminalOutput())
73+
packageInstallationProcessStepTracker.advanceStep(to:
74+
.unexpectedTerminalOutput(rawOutput.containsErrors ? .containedErrors(rawOutput: rawOutput) : .didNotContainErrors(rawOutput: rawOutput))
75+
)
6976
}
7077
}
7178
}

Cork/Views/Installation/Sub-Views/Presenting Search Results.swift

Lines changed: 14 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,25 +18,26 @@ struct PresentingSearchResultsView: View
1818
@InjectedObservable(\.appState) var appState: AppState
1919

2020
@Environment(PackageInstallationProcessStepTracker.self) var packageInstallationProcessStepTracker
21-
21+
2222
@State private var searchString: String = ""
23-
23+
2424
@Binding var selectedPackage: MinimalHomebrewPackage?
25-
25+
2626
let foundFormulae: [MinimalHomebrewPackage]
2727
let foundCasks: [MinimalHomebrewPackage]
2828

2929
@State private var isFormulaeSectionCollapsed: Bool = false
3030
@State private var isCasksSectionCollapsed: Bool = false
3131

3232
@State var isSearchFieldFocused: Bool = true
33-
33+
3434
init(
3535
oldSearchString: String,
3636
selectedPackage: Binding<MinimalHomebrewPackage?> = .constant(nil),
3737
foundFormulae: [MinimalHomebrewPackage],
3838
foundCasks: [MinimalHomebrewPackage]
39-
) {
39+
)
40+
{
4041
_searchString = State(initialValue: oldSearchString)
4142
_selectedPackage = selectedPackage
4243
self.foundFormulae = foundFormulae
@@ -160,7 +161,7 @@ struct PresentingSearchResultsView: View
160161
{
161162
AppConstants.shared.logger.error("Impossible case")
162163
}
163-
164+
164165
} label: {
165166
Text("add-package.install.action")
166167
}
@@ -194,25 +195,12 @@ private struct SearchResultsSection: View
194195
{
195196
Group
196197
{
197-
if #available(macOS 14.0, *)
198-
{
199-
switch sectionType
200-
{
201-
case .formula:
202-
SmallerContentUnavailableView(label: "add-package.search.results.formulae.none-found", image: "custom.apple.terminal.badge.magnifyingglass")
203-
case .cask:
204-
SmallerContentUnavailableView(label: "add-package.search.results.casks.none-found", image: "custom.macwindow.badge.magnifyingglass")
205-
}
206-
}
207-
else
198+
switch sectionType
208199
{
209-
switch sectionType
210-
{
211-
case .formula:
212-
Text("add-package.search.results.formulae.none-found")
213-
case .cask:
214-
Text("add-package.search.results.casks.none-found")
215-
}
200+
case .formula:
201+
SmallerContentUnavailableView(label: "add-package.search.results.formulae.none-found", image: "custom.apple.terminal.badge.magnifyingglass")
202+
case .cask:
203+
SmallerContentUnavailableView(label: "add-package.search.results.casks.none-found", image: "custom.macwindow.badge.magnifyingglass")
216204
}
217205
}
218206
.frame(minWidth: 0, maxWidth: .infinity, alignment: .center)
@@ -225,15 +213,15 @@ private struct SearchResultsSection: View
225213
{
226214
ForEach(packageList)
227215
{ package in
228-
SearchResultRow(searchedForPackage: package, context: .searchResults)
216+
SearchResultRow(context: .searchResult(searchedForPackage: package))
229217
}
230218
}
231219
} header: {
232220
CollapsibleSectionHeader(headerText: sectionType == .formula ? "add-package.search.results.formulae" : "add-package.search.results.casks", isCollapsed: $isSectionCollapsed)
233221
}
234222
}
235223
}
236-
224+
237225
@ViewBuilder
238226
private var searchFailed: some View
239227
{

Cork/Views/Sidebar/Components/Sidebar Package Row.swift

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ struct SidebarPackageRow: View
3131
}
3232
.contextMenu
3333
{
34-
SidebarContextMenu(package: package)
34+
package.contextMenu(using: package)
35+
{
36+
SidebarContextMenu(package: package)
37+
}
3538
}
3639
.modify
3740
{ viewProxy in

Modules/Packages/PackagesModels/Logic/Installation & Removal/Synchnorize Installed Packages.swift

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ public extension BrewPackagesTracker
1818
{
1919
AppConstants.shared.logger.debug("Will start synchronization process")
2020

21+
/// Save the old casks, we will compare them to see if we need to reload adoptable apps later
22+
let oldLoadedCasks: Set<BrewPackage> = self.successfullyLoadedCasks
23+
2124
async let updatedFormulaeTracker: BrewPackages? = await self.loadInstalledPackages(packageTypeToLoad: .formula, appState: AppState())
2225
async let updatedCasksTracker: BrewPackages? = await self.loadInstalledPackages(packageTypeToLoad: .cask, appState: AppState())
2326

@@ -34,11 +37,21 @@ public extension BrewPackagesTracker
3437

3538
await cachedDownloadsTracker.loadCachedDownloadedPackages(brewPackagesTracker: self)
3639

37-
do
40+
AppConstants.shared.logger.debug("Number of old packages: \(oldLoadedCasks.count), Number of new packages: \(self.successfullyLoadedCasks.count)")
41+
42+
if self.successfullyLoadedCasks.count != oldLoadedCasks.count
43+
{
44+
do
45+
{
46+
47+
self.adoptableApps = try await self.getAdoptableCasks(cacheUsePolicy: .useCachedData)
48+
} catch let adoptableCasksSynchronizationError {
49+
AppConstants.shared.logger.error("Failed while synchronizing adoptable casks: \(adoptableCasksSynchronizationError)")
50+
}
51+
}
52+
else
3853
{
39-
self.adoptableApps = try await self.getAdoptableCasks(cacheUsePolicy: .useCachedData)
40-
} catch let adoptableCasksSynchronizationError {
41-
AppConstants.shared.logger.error("Failed while synchronizing adoptable casks: \(adoptableCasksSynchronizationError)")
54+
AppConstants.shared.logger.error("No changes to packages. No need to reload the adoptable apps.")
4255
}
4356
}
4457
}

Modules/Packages/PackagesModels/Logic/Taps/Load Tap Details.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,11 +59,15 @@ public extension BrewTap
5959
guard let tapInfoRaw: Data = tapInfoLoadingResult.getJsonFromOutput(failOnAnyErrorsPresent: false)
6060
else
6161
{
62+
appConstants.logger.info("Couldn't get any data from JSON output")
63+
6264
throw .couldNotReadJson
6365
}
6466

6567
do
6668
{
69+
appConstants.logger.info("got valid data from JSON output: \(tapInfoRaw)")
70+
6771
self.setBeingLoadedStatus(to: false)
6872

6973
return try await .init(from: tapInfoRaw)

0 commit comments

Comments
 (0)