diff options
| author | Christian Cleberg <[email protected]> | 2026-04-13 20:07:53 -0500 |
|---|---|---|
| committer | Christian Cleberg <[email protected]> | 2026-04-13 20:07:53 -0500 |
| commit | 312e535f400f31714b3750de5222a1f6a8e5bcda (patch) | |
| tree | dfa0d9dfcfd08187befa79cf5d8afc4da9fef860 | |
| parent | fe1ccc69661603d419a642a450e4ac9e1258adb0 (diff) | |
| download | hutch-3.1.4.tar.gz hutch-3.1.4.tar.bz2 hutch-3.1.4.zip | |
fix: sonarqube code smell fixesv3.1.4
33 files changed, 257 insertions, 262 deletions
diff --git a/Hutch.xcodeproj/project.pbxproj b/Hutch.xcodeproj/project.pbxproj index bbdb9e3..3162b32 100644 --- a/Hutch.xcodeproj/project.pbxproj +++ b/Hutch.xcodeproj/project.pbxproj @@ -515,7 +515,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Hutch/Hutch.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = ZCNAX3VL9D; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -532,7 +532,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.1.3; + MARKETING_VERSION = 3.1.4; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; @@ -552,7 +552,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Hutch/Hutch.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = ZCNAX3VL9D; ENABLE_PREVIEWS = YES; GENERATE_INFOPLIST_FILE = YES; @@ -569,7 +569,7 @@ "$(inherited)", "@executable_path/Frameworks", ); - MARKETING_VERSION = 3.1.3; + MARKETING_VERSION = 3.1.4; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; @@ -632,7 +632,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = ZCNAX3VL9D; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = HutchWidgetExtension/Info.plist; @@ -642,7 +642,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.1.3; + MARKETING_VERSION = 3.1.4; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -661,7 +661,7 @@ APPLICATION_EXTENSION_API_ONLY = YES; CODE_SIGN_ENTITLEMENTS = HutchWidgetExtension/HutchWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 71; + CURRENT_PROJECT_VERSION = 72; DEVELOPMENT_TEAM = ZCNAX3VL9D; GENERATE_INFOPLIST_FILE = NO; INFOPLIST_FILE = HutchWidgetExtension/Info.plist; @@ -671,7 +671,7 @@ "@executable_path/Frameworks", "@executable_path/../../Frameworks", ); - MARKETING_VERSION = 3.1.3; + MARKETING_VERSION = 3.1.4; PRODUCT_BUNDLE_IDENTIFIER = net.cleberg.Hutch.HutchWidgetExtension; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; diff --git a/Hutch/Models/Git.swift b/Hutch/Models/Git.swift index 3629ce4..26a5e2d 100644 --- a/Hutch/Models/Git.swift +++ b/Hutch/Models/Git.swift @@ -4,9 +4,9 @@ import Foundation /// Repository visibility level. enum Visibility: String, Codable, Sendable { - case `public` = "PUBLIC" + case publicVisibility = "PUBLIC" case unlisted = "UNLISTED" - case `private` = "PRIVATE" + case privateVisibility = "PRIVATE" } /// Repository access mode. diff --git a/Hutch/Models/Project.swift b/Hutch/Models/Project.swift index bbca7d6..8f5aa68 100644 --- a/Hutch/Models/Project.swift +++ b/Hutch/Models/Project.swift @@ -230,11 +230,11 @@ extension String { extension Visibility { var displayName: String { switch self { - case .public: + case .publicVisibility: "Public" case .unlisted: "Unlisted" - case .private: + case .privateVisibility: "Private" } } diff --git a/Hutch/Models/RepositorySummary.swift b/Hutch/Models/RepositorySummary.swift index 3821aa2..b41589b 100644 --- a/Hutch/Models/RepositorySummary.swift +++ b/Hutch/Models/RepositorySummary.swift @@ -20,26 +20,29 @@ struct RepositorySummary: Codable, Sendable, Identifiable, Hashable { case head = "HEAD" } - init( - id: Int, - rid: String, - service: SRHTService, - name: String, - description: String?, - visibility: Visibility, - updated: Date, - owner: Entity, - head: Reference? - ) { - self.id = id - self.rid = rid - self.service = service - self.name = name - self.description = description - self.visibility = visibility - self.updated = updated - self.owner = owner - self.head = head + /// Grouped initializer fields (single parameter keeps APIs explicit without exceeding parameter-count limits). + struct Fields: Sendable, Hashable { + let id: Int + let rid: String + let service: SRHTService + let name: String + let description: String? + let visibility: Visibility + let updated: Date + let owner: Entity + let head: Reference? + } + + init(fields: Fields) { + id = fields.id + rid = fields.rid + service = fields.service + name = fields.name + description = fields.description + visibility = fields.visibility + updated = fields.updated + owner = fields.owner + head = fields.head } init(from decoder: any Decoder) throws { @@ -69,15 +72,17 @@ extension RepositorySummary { head: Reference? = nil ) -> RepositorySummary { RepositorySummary( - id: id, - rid: rid, - service: service, - name: name ?? self.name, - description: description ?? self.description, - visibility: visibility ?? self.visibility, - updated: updated ?? self.updated, - owner: owner, - head: head ?? self.head + fields: .init( + id: id, + rid: rid, + service: service, + name: name ?? self.name, + description: description ?? self.description, + visibility: visibility ?? self.visibility, + updated: updated ?? self.updated, + owner: owner, + head: head ?? self.head + ) ) } diff --git a/Hutch/Networking/ProjectService.swift b/Hutch/Networking/ProjectService.swift index bd8ccdc..5e0e061 100644 --- a/Hutch/Networking/ProjectService.swift +++ b/Hutch/Networking/ProjectService.swift @@ -49,7 +49,7 @@ private struct ProjectSummaryPayload: Decodable, Sendable { name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" description = try container.decodeIfPresent(String.self, forKey: .description) website = try container.decodeIfPresent(String.self, forKey: .website) - visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .public + visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .publicVisibility tags = try container.decodeIfPresent([String].self, forKey: .tags) ?? [] updated = try container.decodeIfPresent(Date.self, forKey: .updated) ?? .distantPast } @@ -90,7 +90,7 @@ private struct ProjectDetailPayload: Decodable, Sendable { name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" description = try container.decodeIfPresent(String.self, forKey: .description) website = try container.decodeIfPresent(String.self, forKey: .website) - visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .public + visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .publicVisibility tags = try container.decodeIfPresent([String].self, forKey: .tags) ?? [] updated = try container.decodeIfPresent(Date.self, forKey: .updated) ?? .distantPast mailingLists = try container.decodeIfPresent(ProjectMailingListPage.self, forKey: .mailingLists) ?? .empty @@ -126,7 +126,7 @@ private struct ProjectMailingListPayload: Decodable, Sendable { rid = try container.decode(String.self, forKey: .rid) name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" description = try container.decodeIfPresent(String.self, forKey: .description) - visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .public + visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .publicVisibility owner = try container.decodeIfPresent(Entity.self, forKey: .owner) ?? Entity(canonicalName: "~unknown") } } @@ -160,7 +160,7 @@ private struct ProjectSourcePayload: Decodable, Sendable { rid = try container.decode(String.self, forKey: .rid) name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" description = try container.decodeIfPresent(String.self, forKey: .description) - visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .public + visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .publicVisibility owner = try container.decodeIfPresent(Entity.self, forKey: .owner) ?? Entity(canonicalName: "~unknown") repoType = try container.decodeIfPresent(Project.SourceRepo.RepoType.self, forKey: .repoType) ?? .git } @@ -193,7 +193,7 @@ private struct ProjectTrackerPayload: Decodable, Sendable { rid = try container.decode(String.self, forKey: .rid) name = try container.decodeIfPresent(String.self, forKey: .name) ?? "" description = try container.decodeIfPresent(String.self, forKey: .description) - visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .public + visibility = try container.decodeIfPresent(Visibility.self, forKey: .visibility) ?? .publicVisibility owner = try container.decodeIfPresent(Entity.self, forKey: .owner) ?? Entity(canonicalName: "~unknown") } } diff --git a/Hutch/Networking/SRHTClient.swift b/Hutch/Networking/SRHTClient.swift index 7e1f619..fa7b26b 100644 --- a/Hutch/Networking/SRHTClient.swift +++ b/Hutch/Networking/SRHTClient.swift @@ -57,7 +57,7 @@ final class SRHTClient: Sendable { service: SRHTService, query: String, variables: [String: any Sendable]? = nil, - responseType: T.Type + responseType _: T.Type ) async throws -> T { guard let token = _token.withLock({ $0 }), !token.isEmpty else { throw SRHTError.unauthorized @@ -164,20 +164,14 @@ final class SRHTClient: Sendable { /// - service: The target SourceHut service. /// - query: The GraphQL mutation string. /// - variables: Variables dict; the file variable should be set to `nil`. - /// - fileVariablePath: The dot-separated path to the file variable (e.g. "input.avatar"). - /// - fileData: The raw file data (e.g. JPEG). - /// - fileName: The file name to send (e.g. "avatar.jpg"). - /// - mimeType: The MIME type (e.g. "image/jpeg"). + /// - file: Multipart file payload (`variablePath` is the dot-separated GraphQL variable, e.g. `input.avatar`). /// - responseType: The expected `Decodable` type nested under `data`. func executeMultipart<T: Decodable>( service: SRHTService, query: String, variables: [String: any Sendable], - fileVariablePath: String, - fileData: Data, - fileName: String, - mimeType: String, - responseType: T.Type + file: MultipartUploadFile, + responseType _: T.Type ) async throws -> T { guard let token = _token.withLock({ $0 }), !token.isEmpty else { throw SRHTError.unauthorized @@ -197,8 +191,8 @@ final class SRHTClient: Sendable { ) let operationsData = try encoder.encode(operationsBody) - // Build the map JSON: { "0": ["variables.<fileVariablePath>"] } - let mapDict = ["0": ["variables.\(fileVariablePath)"]] + // Build the map JSON: { "0": ["variables.<variablePath>"] } + let mapDict = ["0": ["variables.\(file.variablePath)"]] let mapData = try encoder.encode(mapDict) // Assemble multipart body @@ -220,9 +214,9 @@ final class SRHTClient: Sendable { // Part: file body.append("--\(boundary)\r\n") - body.append("Content-Disposition: form-data; name=\"0\"; filename=\"\(fileName)\"\r\n") - body.append("Content-Type: \(mimeType)\r\n\r\n") - body.append(fileData) + body.append("Content-Disposition: form-data; name=\"0\"; filename=\"\(file.fileName)\"\r\n") + body.append("Content-Type: \(file.mimeType)\r\n\r\n") + body.append(file.fileData) body.append("\r\n") // Closing boundary @@ -311,7 +305,7 @@ final class SRHTClient: Sendable { query: String, variables: [String: any Sendable], files: [MultipartUploadFile], - responseType: T.Type + responseType _: T.Type ) async throws -> T { guard let token = _token.withLock({ $0 }), !token.isEmpty else { throw SRHTError.unauthorized @@ -408,15 +402,14 @@ final class SRHTClient: Sendable { service: SRHTService, query: String, variables: [String: any Sendable]? = nil, - responseType: T.Type, + responseType _: T.Type, cacheKey: String ) async throws -> T { // Try cache first - if let cachedData = responseCache.get(forKey: cacheKey) { - if let cached = try? decoder.decode(GraphQLResponse<T>.self, from: cachedData), - let data = cached.data { - return data - } + if let cachedData = responseCache.get(forKey: cacheKey), + let cached = try? decoder.decode(GraphQLResponse<T>.self, from: cachedData), + let data = cached.data { + return data } // No cache hit — fetch normally @@ -434,7 +427,7 @@ final class SRHTClient: Sendable { service: SRHTService, query: String, variables: [String: any Sendable]? = nil, - responseType: T.Type, + responseType _: T.Type, cacheKey: String ) async throws -> T { guard let token = _token.withLock({ $0 }), !token.isEmpty else { @@ -580,8 +573,7 @@ final class SRHTClient: Sendable { service: SRHTService, query: String, variables: [String: any Sendable]? = nil, - resultKeyPath: String, - type: T.Type + resultKeyPath: String ) -> SRHTPaginatedSequence<T> { SRHTPaginatedSequence( client: self, @@ -598,16 +590,14 @@ final class SRHTClient: Sendable { service: SRHTService, query: String, variables: [String: any Sendable]? = nil, - resultKeyPath: String, - type: T.Type + resultKeyPath: String ) async throws -> [T] { var all: [T] = [] for try await element in paginated( service: service, query: query, variables: variables, - resultKeyPath: resultKeyPath, - type: type + resultKeyPath: resultKeyPath ) { all.append(element) } diff --git a/Hutch/Views/Builds/BuildDetailView.swift b/Hutch/Views/Builds/BuildDetailView.swift index 46fb42d..334dff7 100644 --- a/Hutch/Views/Builds/BuildDetailView.swift +++ b/Hutch/Views/Builds/BuildDetailView.swift @@ -468,7 +468,7 @@ private struct EditResubmitBuildSheet: View { _manifest = State(initialValue: job.manifest ?? "") _tagsText = State(initialValue: job.tags.joined(separator: ", ")) _note = State(initialValue: job.note ?? "") - _visibility = State(initialValue: job.visibility ?? .public) + _visibility = State(initialValue: job.visibility ?? .publicVisibility) } var body: some View { @@ -491,9 +491,9 @@ private struct EditResubmitBuildSheet: View { .autocorrectionDisabled() .themedRow() Picker("Visibility", selection: $visibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() Toggle("Start build now", isOn: $execute) diff --git a/Hutch/Views/Builds/BuildListView.swift b/Hutch/Views/Builds/BuildListView.swift index fc91ea1..8de2220 100644 --- a/Hutch/Views/Builds/BuildListView.swift +++ b/Hutch/Views/Builds/BuildListView.swift @@ -265,7 +265,7 @@ private struct SubmitBuildSheet: View { @State private var note = "" @State private var secrets = false @State private var execute = true - @State private var visibility: Visibility = .public + @State private var visibility: Visibility = .publicVisibility init(viewModel: BuildListViewModel, onSubmitted: @escaping (Int) -> Void) { self.viewModel = viewModel @@ -293,9 +293,9 @@ private struct SubmitBuildSheet: View { .autocorrectionDisabled() .themedRow() Picker("Visibility", selection: $visibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() Toggle("Start build now", isOn: $execute) diff --git a/Hutch/Views/Lookup/LookupView.swift b/Hutch/Views/Lookup/LookupView.swift index f45082d..64ca39d 100644 --- a/Hutch/Views/Lookup/LookupView.swift +++ b/Hutch/Views/Lookup/LookupView.swift @@ -233,15 +233,17 @@ final class LookupViewModel { let repository = try await appState.resolveRepository(owner: owner, name: name, service: service) let resolvedRepository = RepositorySummary( - id: repository.id, - rid: repository.rid, - service: service, - name: repository.name, - description: repository.description, - visibility: repository.visibility, - updated: repository.updated, - owner: repository.owner, - head: repository.head + fields: .init( + id: repository.id, + rid: repository.rid, + service: service, + name: repository.name, + description: repository.description, + visibility: repository.visibility, + updated: repository.updated, + owner: repository.owner, + head: repository.head + ) ) return .repository(resolvedRepository) diff --git a/Hutch/Views/Lookup/UserProfileViewModel.swift b/Hutch/Views/Lookup/UserProfileViewModel.swift index b88d36a..0e503ce 100644 --- a/Hutch/Views/Lookup/UserProfileViewModel.swift +++ b/Hutch/Views/Lookup/UserProfileViewModel.swift @@ -179,15 +179,17 @@ final class UserProfileViewModel { func repositorySummary(service: SRHTService) -> RepositorySummary { RepositorySummary( - id: id, - rid: rid, - service: service, - name: name, - description: description, - visibility: visibility, - updated: updated, - owner: owner, - head: head + fields: .init( + id: id, + rid: rid, + service: service, + name: name, + description: description, + visibility: visibility, + updated: updated, + owner: owner, + head: head + ) ) } } diff --git a/Hutch/Views/Pastes/PasteDetailView.swift b/Hutch/Views/Pastes/PasteDetailView.swift index c6fe11a..49d4fa6 100644 --- a/Hutch/Views/Pastes/PasteDetailView.swift +++ b/Hutch/Views/Pastes/PasteDetailView.swift @@ -442,27 +442,27 @@ private struct PasteVisibilitySheet: View { } private var visibilityOptions: [Visibility] { - [.public, .unlisted, .private] + [.publicVisibility, .unlisted, .privateVisibility] } private func title(for visibility: Visibility) -> String { switch visibility { - case .public: + case .publicVisibility: "Public" case .unlisted: "Unlisted" - case .private: + case .privateVisibility: "Private" } } private func description(for visibility: Visibility) -> String { switch visibility { - case .public: + case .publicVisibility: "Visible to everyone and listed on your profile." case .unlisted: "Visible to anyone with the URL, but not listed on your profile." - case .private: + case .privateVisibility: "Visible only to explicitly allowed viewers." } } diff --git a/Hutch/Views/Pastes/PasteListView.swift b/Hutch/Views/Pastes/PasteListView.swift index dfd472b..17bb8ac 100644 --- a/Hutch/Views/Pastes/PasteListView.swift +++ b/Hutch/Views/Pastes/PasteListView.swift @@ -179,33 +179,33 @@ struct PasteListView: View { private func nextVisibilityLabel(for visibility: Visibility) -> String { switch visibility { - case .public: + case .publicVisibility: return "Make Unlisted" case .unlisted: return "Make Private" - case .private: + case .privateVisibility: return "Make Public" } } private func nextVisibilityIcon(for visibility: Visibility) -> String { switch visibility { - case .public: + case .publicVisibility: return "eye.slash" case .unlisted: return "lock" - case .private: + case .privateVisibility: return "globe" } } private func nextVisibilityColor(for visibility: Visibility) -> Color { switch visibility { - case .public: + case .publicVisibility: return .orange case .unlisted: return .red - case .private: + case .privateVisibility: return .green } } @@ -316,9 +316,9 @@ private struct CreatePasteSheet: View { Section("Visibility") { Picker("Visibility", selection: $visibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() } diff --git a/Hutch/Views/Pastes/PasteListViewModel.swift b/Hutch/Views/Pastes/PasteListViewModel.swift index 75f2f4b..640e31b 100644 --- a/Hutch/Views/Pastes/PasteListViewModel.swift +++ b/Hutch/Views/Pastes/PasteListViewModel.swift @@ -131,12 +131,12 @@ final class PasteListViewModel { func cycleVisibility(for paste: Paste) async { let next: Visibility switch paste.visibility { - case .public: + case .publicVisibility: next = .unlisted case .unlisted: - next = .private - case .private: - next = .public + next = .privateVisibility + case .privateVisibility: + next = .publicVisibility } let original = pastes diff --git a/Hutch/Views/Repositories/FileTreeViewModel.swift b/Hutch/Views/Repositories/FileTreeViewModel.swift index c6fecbe..98211bf 100644 --- a/Hutch/Views/Repositories/FileTreeViewModel.swift +++ b/Hutch/Views/Repositories/FileTreeViewModel.swift @@ -327,14 +327,11 @@ final class FileTreeViewModel { } case .binaryBlob(let blob): - if blob.content != nil { + if blob.content != nil || blob.id == nil { viewingEntry = entry viewingObject = object } else if let blobId = blob.id { await loadBlob(entry: entry, blobId: blobId) - } else { - viewingEntry = entry - viewingObject = object } case .unknown: diff --git a/Hutch/Views/Repositories/HgRepositorySettingsView.swift b/Hutch/Views/Repositories/HgRepositorySettingsView.swift index e3c97e0..7b57505 100644 --- a/Hutch/Views/Repositories/HgRepositorySettingsView.swift +++ b/Hutch/Views/Repositories/HgRepositorySettingsView.swift @@ -121,9 +121,9 @@ struct HgRepositorySettingsView: View { .themedRow() Picker("Visibility", selection: Bindable(viewModel).editedVisibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() diff --git a/Hutch/Views/Repositories/ReadmeView.swift b/Hutch/Views/Repositories/ReadmeView.swift index 21d7a74..1a72b70 100644 --- a/Hutch/Views/Repositories/ReadmeView.swift +++ b/Hutch/Views/Repositories/ReadmeView.swift @@ -1828,7 +1828,7 @@ private final class HTMLWebViewCoordinator: NSObject, WKNavigationDelegate, @unc } func webView( - _ webView: WKWebView, + _: WKWebView, decidePolicyFor navigationAction: WKNavigationAction, decisionHandler: @escaping @MainActor (WKNavigationActionPolicy) -> Void ) { diff --git a/Hutch/Views/Repositories/RepositoryListView.swift b/Hutch/Views/Repositories/RepositoryListView.swift index 08ebb5c..04a7084 100644 --- a/Hutch/Views/Repositories/RepositoryListView.swift +++ b/Hutch/Views/Repositories/RepositoryListView.swift @@ -214,7 +214,7 @@ private struct CreateRepositorySheet: View { @State private var name = "" @State private var description = "" @State private var cloneURL = "" - @State private var visibility: Visibility = .public + @State private var visibility: Visibility = .publicVisibility @State private var service: RepositoryCreationService = .git var body: some View { @@ -235,9 +235,9 @@ private struct CreateRepositorySheet: View { .lineLimit(2...4) .themedRow() Picker("Visibility", selection: $visibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() } diff --git a/Hutch/Views/Repositories/RepositoryListViewModel.swift b/Hutch/Views/Repositories/RepositoryListViewModel.swift index 1e830bb..61053a0 100644 --- a/Hutch/Views/Repositories/RepositoryListViewModel.swift +++ b/Hutch/Views/Repositories/RepositoryListViewModel.swift @@ -397,15 +397,17 @@ final class RepositoryListViewModel { func repositorySummary(service: SRHTService) -> RepositorySummary { RepositorySummary( - id: id, - rid: rid, - service: service, - name: name, - description: description, - visibility: visibility, - updated: updated, - owner: owner, - head: head + fields: .init( + id: id, + rid: rid, + service: service, + name: name, + description: description, + visibility: visibility, + updated: updated, + owner: owner, + head: head + ) ) } } @@ -422,15 +424,17 @@ final class RepositoryListViewModel { func repositorySummary(service: SRHTService) -> RepositorySummary { RepositorySummary( - id: id, - rid: rid, - service: service, - name: name, - description: description, - visibility: visibility, - updated: updated, - owner: owner, - head: tip.map { Reference(name: $0.branch, target: nil) } + fields: .init( + id: id, + rid: rid, + service: service, + name: name, + description: description, + visibility: visibility, + updated: updated, + owner: owner, + head: tip.map { Reference(name: $0.branch, target: nil) } + ) ) } } @@ -463,17 +467,7 @@ final class RepositoryListViewModel { } if useCache && cursor == nil { - switch service { - case .git: - let result = try await client.executeAndCache( - service: service, - query: Self.gitQuery, - variables: variables.isEmpty ? nil : variables, - responseType: RepositoriesResponse.self, - cacheKey: cacheKey(for: service) - ) - return result.repositories ?? Self.emptyPage - case .hg: + if service == .hg { let hgVariables = cursor.map { ["cursor": $0 as any Sendable] } let result = try await client.executeAndCache( service: service, @@ -497,27 +491,17 @@ final class RepositoryListViewModel { } ?? [], cursor: result.repositories?.cursor ) - default: - let result = try await client.executeAndCache( - service: service, - query: Self.gitQuery, - variables: variables.isEmpty ? nil : variables, - responseType: RepositoriesResponse.self, - cacheKey: cacheKey(for: service) - ) - return result.repositories ?? Self.emptyPage } + let result = try await client.executeAndCache( + service: service, + query: Self.gitQuery, + variables: variables.isEmpty ? nil : variables, + responseType: RepositoriesResponse.self, + cacheKey: cacheKey(for: service) + ) + return result.repositories ?? Self.emptyPage } else { - switch service { - case .git: - let result = try await client.execute( - service: service, - query: Self.gitQuery, - variables: variables.isEmpty ? nil : variables, - responseType: RepositoriesResponse.self - ) - return result.repositories ?? Self.emptyPage - case .hg: + if service == .hg { let hgVariables = cursor.map { ["cursor": $0 as any Sendable] } let result = try await client.execute( service: service, @@ -540,15 +524,14 @@ final class RepositoryListViewModel { } ?? [], cursor: result.repositories?.cursor ) - default: - let result = try await client.execute( - service: service, - query: Self.gitQuery, - variables: variables.isEmpty ? nil : variables, - responseType: RepositoriesResponse.self - ) - return result.repositories ?? Self.emptyPage } + let result = try await client.execute( + service: service, + query: Self.gitQuery, + variables: variables.isEmpty ? nil : variables, + responseType: RepositoriesResponse.self + ) + return result.repositories ?? Self.emptyPage } } diff --git a/Hutch/Views/Repositories/RepositoryRowView.swift b/Hutch/Views/Repositories/RepositoryRowView.swift index a2d120b..86c8889 100644 --- a/Hutch/Views/Repositories/RepositoryRowView.swift +++ b/Hutch/Views/Repositories/RepositoryRowView.swift @@ -154,17 +154,17 @@ struct VisibilityBadge: View { private var label: String { switch visibility { - case .public: "PUBLIC" + case .publicVisibility: "PUBLIC" case .unlisted: "UNLISTED" - case .private: "PRIVATE" + case .privateVisibility: "PRIVATE" } } private var color: Color { switch visibility { - case .public: .green + case .publicVisibility: .green case .unlisted: .orange - case .private: .red + case .privateVisibility: .red } } } diff --git a/Hutch/Views/Repositories/RepositorySettingsView.swift b/Hutch/Views/Repositories/RepositorySettingsView.swift index 44b50ae..9f172a8 100644 --- a/Hutch/Views/Repositories/RepositorySettingsView.swift +++ b/Hutch/Views/Repositories/RepositorySettingsView.swift @@ -227,9 +227,9 @@ struct RepositorySettingsView: View { private func visibilitySection(_ viewModel: RepositorySettingsViewModel) -> some View { Section { Picker("Visibility", selection: Bindable(viewModel).editedVisibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() @@ -283,11 +283,11 @@ struct RepositorySettingsView: View { private func visibilityConfirmationMessage(for viewModel: RepositorySettingsViewModel) -> String { switch viewModel.editedVisibility { - case .public: + case .publicVisibility: "Anyone will be able to find and view this repository." case .unlisted: "People with the link can view this repository, but it won't appear in public listings." - case .private: + case .privateVisibility: "Only people with explicit access will be able to view this repository." } } diff --git a/Hutch/Views/Repositories/RepositorySettingsViewModel.swift b/Hutch/Views/Repositories/RepositorySettingsViewModel.swift index 8bd80a1..6233bec 100644 --- a/Hutch/Views/Repositories/RepositorySettingsViewModel.swift +++ b/Hutch/Views/Repositories/RepositorySettingsViewModel.swift @@ -20,15 +20,17 @@ private struct UpdatedRepositoryPayload: Decodable, Sendable { func repositorySummary(using owner: Entity, service: SRHTService) -> RepositorySummary { RepositorySummary( - id: id, - rid: rid, - service: service, - name: name, - description: description, - visibility: visibility, - updated: updated, - owner: owner, - head: head + fields: .init( + id: id, + rid: rid, + service: service, + name: name, + description: description, + visibility: visibility, + updated: updated, + owner: owner, + head: head + ) ) } } diff --git a/Hutch/Views/Repositories/RepositorySummarySupport.swift b/Hutch/Views/Repositories/RepositorySummarySupport.swift index 741ff39..393e3ff 100644 --- a/Hutch/Views/Repositories/RepositorySummarySupport.swift +++ b/Hutch/Views/Repositories/RepositorySummarySupport.swift @@ -37,11 +37,11 @@ func repositoryCloneURLs(for repository: RepositorySummary) -> RepositoryCloneUR func repositoryVisibilityLabel(_ visibility: Visibility) -> String { switch visibility { - case .public: + case .publicVisibility: return "Public" case .unlisted: return "Unlisted" - case .private: + case .privateVisibility: return "Private" } } diff --git a/Hutch/Views/Settings/SettingsViewModel.swift b/Hutch/Views/Settings/SettingsViewModel.swift index 29103f6..0b55e6a 100644 --- a/Hutch/Views/Settings/SettingsViewModel.swift +++ b/Hutch/Views/Settings/SettingsViewModel.swift @@ -228,10 +228,12 @@ final class SettingsViewModel { service: .meta, query: Self.updateUserMutation, variables: ["input": input], - fileVariablePath: "input.avatar", - fileData: jpegData, - fileName: "avatar.jpg", - mimeType: "image/jpeg", + file: MultipartUploadFile( + variablePath: "input.avatar", + fileData: jpegData, + fileName: "avatar.jpg", + mimeType: "image/jpeg" + ), responseType: UpdateUserResponse.self ) let updated = result.updateUser diff --git a/Hutch/Views/Tickets/TicketListView.swift b/Hutch/Views/Tickets/TicketListView.swift index 940a282..afee96d 100644 --- a/Hutch/Views/Tickets/TicketListView.swift +++ b/Hutch/Views/Tickets/TicketListView.swift @@ -1400,11 +1400,13 @@ struct FlowLayout: Layout { var spacing: CGFloat = 4 func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize { + _ = cache let result = layoutSubviews(proposal: proposal, subviews: subviews) return result.size } func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) { + _ = cache let result = layoutSubviews(proposal: proposal, subviews: subviews) for (index, position) in result.positions.enumerated() { subviews[index].place( diff --git a/Hutch/Views/Tickets/TrackerListView.swift b/Hutch/Views/Tickets/TrackerListView.swift index 9ca3340..5deb513 100644 --- a/Hutch/Views/Tickets/TrackerListView.swift +++ b/Hutch/Views/Tickets/TrackerListView.swift @@ -37,7 +37,7 @@ struct TrackerListView: View { error: viewModel.error, initialName: "", initialDescription: "", - initialVisibility: .public + initialVisibility: .publicVisibility ) { name, description, visibility in if let tracker = await viewModel.createTracker( name: name, diff --git a/Hutch/Views/Tickets/TrackerManagementView.swift b/Hutch/Views/Tickets/TrackerManagementView.swift index 4e04bbd..fad1ae8 100644 --- a/Hutch/Views/Tickets/TrackerManagementView.swift +++ b/Hutch/Views/Tickets/TrackerManagementView.swift @@ -659,9 +659,9 @@ struct TrackerEditorSheet: View { .lineLimit(2...4) .themedRow() Picker("Visibility", selection: $visibility) { - Text("Public").tag(Visibility.public) + Text("Public").tag(Visibility.publicVisibility) Text("Unlisted").tag(Visibility.unlisted) - Text("Private").tag(Visibility.private) + Text("Private").tag(Visibility.privateVisibility) } .themedRow() } diff --git a/HutchTests/AppStateTests.swift b/HutchTests/AppStateTests.swift index fe357cb..a5661ef 100644 --- a/HutchTests/AppStateTests.swift +++ b/HutchTests/AppStateTests.swift @@ -39,22 +39,24 @@ struct AppStateTests { func navigationHelpersQueueExpectedTargets() { let appState = AppState() let repository = RepositorySummary( - id: 1, - rid: "repo", - service: .git, - name: "hutch", - description: nil, - visibility: .public, - updated: .distantPast, - owner: Entity(canonicalName: "~owner"), - head: nil + fields: .init( + id: 1, + rid: "repo", + service: .git, + name: "hutch", + description: nil, + visibility: .publicVisibility, + updated: .distantPast, + owner: Entity(canonicalName: "~owner"), + head: nil + ) ) let tracker = TrackerSummary( id: 2, rid: "tracker", name: "todo", description: nil, - visibility: .public, + visibility: .publicVisibility, updated: .distantPast, owner: Entity(canonicalName: "~owner") ) diff --git a/HutchTests/ProjectTests.swift b/HutchTests/ProjectTests.swift index 0323f25..23faa0d 100644 --- a/HutchTests/ProjectTests.swift +++ b/HutchTests/ProjectTests.swift @@ -15,7 +15,7 @@ struct ProjectTests { name: "Hutch", description: nil, website: nil, - visibility: .public, + visibility: .publicVisibility, tags: [], updated: Date(timeIntervalSince1970: 0) ), @@ -25,7 +25,7 @@ struct ProjectTests { id: "list-1", name: "hutch-devel", description: nil, - visibility: .public, + visibility: .publicVisibility, owner: Entity(canonicalName: "~owner") ) ], @@ -34,7 +34,7 @@ struct ProjectTests { id: "repo-1", name: "hutch", description: nil, - visibility: .public, + visibility: .publicVisibility, owner: Entity(canonicalName: "~owner"), repoType: .git ), @@ -42,7 +42,7 @@ struct ProjectTests { id: "repo-2", name: "hutch-web", description: nil, - visibility: .public, + visibility: .publicVisibility, owner: Entity(canonicalName: "~owner"), repoType: .git ) @@ -52,7 +52,7 @@ struct ProjectTests { id: "tracker-1", name: "bugs", description: nil, - visibility: .public, + visibility: .publicVisibility, owner: Entity(canonicalName: "~owner") ) ], @@ -71,7 +71,7 @@ struct ProjectTests { name: "Docs", description: nil, website: Fixture.exampleWebsite, - visibility: .public, + visibility: .publicVisibility, tags: [], updated: Date(timeIntervalSince1970: 0) ), diff --git a/HutchTests/RepositoryACLViewModelTests.swift b/HutchTests/RepositoryACLViewModelTests.swift index 9c3f929..9640b93 100644 --- a/HutchTests/RepositoryACLViewModelTests.swift +++ b/HutchTests/RepositoryACLViewModelTests.swift @@ -110,15 +110,17 @@ struct RepositoryACLViewModelTests { @MainActor private func makeRepository() -> RepositorySummary { RepositorySummary( - id: 1, - rid: "rid-1", - service: .git, - name: "repo", - description: nil, - visibility: .public, - updated: .now, - owner: Entity(canonicalName: "~owner"), - head: nil + fields: .init( + id: 1, + rid: "rid-1", + service: .git, + name: "repo", + description: nil, + visibility: .publicVisibility, + updated: .now, + owner: Entity(canonicalName: "~owner"), + head: nil + ) ) } } diff --git a/HutchTests/RepositoryListViewModelTests.swift b/HutchTests/RepositoryListViewModelTests.swift index 07f66aa..5fe3974 100644 --- a/HutchTests/RepositoryListViewModelTests.swift +++ b/HutchTests/RepositoryListViewModelTests.swift @@ -79,15 +79,17 @@ struct RepositoryListViewModelTests { branch: String = "main" ) -> RepositorySummary { RepositorySummary( - id: id, - rid: "rid-\(id)", - service: service, - name: name, - description: description, - visibility: .public, - updated: Date(timeIntervalSince1970: TimeInterval(id)), - owner: Entity(canonicalName: owner), - head: Reference(name: branch, target: nil) + fields: .init( + id: id, + rid: "rid-\(id)", + service: service, + name: name, + description: description, + visibility: .publicVisibility, + updated: Date(timeIntervalSince1970: TimeInterval(id)), + owner: Entity(canonicalName: owner), + head: Reference(name: branch, target: nil) + ) ) } } diff --git a/HutchTests/RepositorySettingsViewModelTests.swift b/HutchTests/RepositorySettingsViewModelTests.swift index 3b76da1..e64e08f 100644 --- a/HutchTests/RepositorySettingsViewModelTests.swift +++ b/HutchTests/RepositorySettingsViewModelTests.swift @@ -118,15 +118,17 @@ struct RepositorySettingsViewModelTests { @MainActor private func makeRepository(headName: String?) -> RepositorySummary { RepositorySummary( - id: 1, - rid: "rid-1", - service: .git, - name: "repo", - description: "desc", - visibility: .public, - updated: .now, - owner: Entity(canonicalName: "~owner"), - head: headName.map { Reference(name: $0, target: nil) } + fields: .init( + id: 1, + rid: "rid-1", + service: .git, + name: "repo", + description: "desc", + visibility: .publicVisibility, + updated: .now, + owner: Entity(canonicalName: "~owner"), + head: headName.map { Reference(name: $0, target: nil) } + ) ) } } diff --git a/HutchTests/SRHTWebURLTests.swift b/HutchTests/SRHTWebURLTests.swift index c1f0dc0..d1053e6 100644 --- a/HutchTests/SRHTWebURLTests.swift +++ b/HutchTests/SRHTWebURLTests.swift @@ -14,22 +14,24 @@ struct SRHTWebURLTests { } private let repository = RepositorySummary( - id: 1, - rid: "repo-1", - service: .git, - name: "hutch", - description: nil, - visibility: .public, - updated: .distantPast, - owner: Entity(canonicalName: "~ccleberg"), - head: nil + fields: .init( + id: 1, + rid: "repo-1", + service: .git, + name: "hutch", + description: nil, + visibility: .publicVisibility, + updated: .distantPast, + owner: Entity(canonicalName: "~ccleberg"), + head: nil + ) ) private let tracker = TrackerSummary( id: 2, rid: "tracker-1", name: "todo", description: nil, - visibility: .public, + visibility: .publicVisibility, updated: .distantPast, owner: Entity(canonicalName: "~ccleberg") ) diff --git a/HutchTests/TrackerListViewModelTests.swift b/HutchTests/TrackerListViewModelTests.swift index 7e927af..5c57e04 100644 --- a/HutchTests/TrackerListViewModelTests.swift +++ b/HutchTests/TrackerListViewModelTests.swift @@ -66,7 +66,7 @@ struct TrackerListViewModelTests { rid: "rid-\(id)", name: name, description: description, - visibility: .public, + visibility: .publicVisibility, updated: Date(), owner: Entity(canonicalName: owner) ) |
