diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index e8c1418..030f22e 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -19,7 +19,7 @@ on: - main jobs: - swiftlint: + lint: runs-on: ubuntu-latest container: image: swift:5.10-noble @@ -33,16 +33,11 @@ jobs: - name: Lint Using swiftlint run: swiftlint lint --strict . - swiftformat: + format: runs-on: ubuntu-latest container: image: swift:5.10-noble steps: - uses: actions/checkout@v2 - - name: Set Up swiftformat - run: | - sudo apt-get update && sudo apt-get install -y unzip curl - unzip ci/swiftformat.zip -d /usr/local/bin/ - chmod +x /usr/local/bin/swiftformat - - name: Lint Using swiftformat - run: swiftformat --lint . + - name: Lint Using swift-format + run: swift format lint -r . diff --git a/.swift-format b/.swift-format new file mode 100644 index 0000000..71b901a --- /dev/null +++ b/.swift-format @@ -0,0 +1,6 @@ +{ + "version": 1, + "indentation": { + "spaces": 4 + } +} diff --git a/.swiftformat b/.swiftformat deleted file mode 100644 index b617f3f..0000000 --- a/.swiftformat +++ /dev/null @@ -1,2 +0,0 @@ ---disable wrapMultilineStatementBraces ---commas inline diff --git a/Sources/Helpers/Color+Hex.swift b/Sources/Helpers/Color+Hex.swift index f71edef..c7a3d27 100644 --- a/Sources/Helpers/Color+Hex.swift +++ b/Sources/Helpers/Color+Hex.swift @@ -15,12 +15,18 @@ extension Color { let hex = hex.trimmingCharacters(in: .alphanumerics.inverted) var int = UInt64() Scanner(string: hex).scanHexInt64(&int) - let red, green, blue: Double + let red: Double + let green: Double + let blue: Double switch hex.count { - case 6: // RGB (24-bit) - (red, green, blue) = (Double((int >> 16) & 0xFF), Double((int >> 8) & 0xFF), Double(int & 0xFF)) - case 8: // ARGB (32-bit) - (red, green, blue) = (Double((int >> 16) & 0xFF), Double((int >> 8) & 0xFF), Double(int & 0xFF)) + case 6: // RGB (24-bit) + (red, green, blue) = ( + Double((int >> 16) & 0xFF), Double((int >> 8) & 0xFF), Double(int & 0xFF) + ) + case 8: // ARGB (32-bit) + (red, green, blue) = ( + Double((int >> 16) & 0xFF), Double((int >> 8) & 0xFF), Double(int & 0xFF) + ) default: (red, green, blue) = (0, 0, 0) } diff --git a/Sources/Helpers/Fake.swift b/Sources/Helpers/Fake.swift index 2c29014..19e5cd0 100644 --- a/Sources/Helpers/Fake.swift +++ b/Sources/Helpers/Fake.swift @@ -20,16 +20,22 @@ enum Fake { moreInfo: "http://voltaserve.com" ) - static func serverCall(_ code: @escaping (CheckedContinuation) -> Void) async throws -> T { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + static func serverCall(_ code: @escaping (CheckedContinuation) -> Void) + async throws -> T + { + try await withCheckedThrowingContinuation { + (continuation: CheckedContinuation) in DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) { code(continuation) } } } - static func serverCall(_ code: @escaping (CheckedContinuation) -> Void) async throws { - try await withCheckedThrowingContinuation { (continuation: CheckedContinuation) in + static func serverCall(_ code: @escaping (CheckedContinuation) -> Void) + async throws + { + try await withCheckedThrowingContinuation { + (continuation: CheckedContinuation) in DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) { code(continuation) } diff --git a/Sources/Helpers/FileExtension.swift b/Sources/Helpers/FileExtension.swift index 11474d5..4b97f4c 100644 --- a/Sources/Helpers/FileExtension.swift +++ b/Sources/Helpers/FileExtension.swift @@ -18,7 +18,7 @@ extension String { func isImage() -> Bool { let imageExtensions = [ ".xpm", ".png", ".jpg", ".jpeg", ".jp2", ".gif", ".webp", - ".tiff", ".tif", ".bmp", ".ico", ".heif", ".xcf", ".svg" + ".tiff", ".tif", ".bmp", ".ico", ".heif", ".xcf", ".svg", ] return imageExtensions.contains(self) } @@ -72,7 +72,7 @@ extension String { func isVideo() -> Bool { let videoExtensions = [ ".ogv", ".ogg", ".mpeg", ".mov", ".mqv", ".mp4", ".webm", - ".3gp", ".3g2", ".avi", ".flv", ".mkv", ".asf", ".m4v" + ".3gp", ".3g2", ".avi", ".flv", ".mkv", ".asf", ".m4v", ] return videoExtensions.contains(self) } @@ -80,7 +80,7 @@ extension String { func isAudio() -> Bool { let audioExtensions = [ ".oga", ".mp3", ".flac", ".midi", ".ape", ".mpc", ".amr", - ".wav", ".aiff", ".au", ".aac", "voc", ".m4a", ".qcp" + ".wav", ".aiff", ".au", ".aac", "voc", ".m4a", ".qcp", ] return audioExtensions.contains(self) } @@ -98,7 +98,7 @@ extension String { let codeExtensions = [ ".html", ".js", "jsx", ".ts", ".tsx", ".css", ".sass", ".scss", ".go", ".py", ".rb", ".java", ".c", ".h", ".cpp", - ".hpp", ".json", ".yml", ".yaml", ".toml", ".md" + ".hpp", ".json", ".yml", ".yaml", ".toml", ".md", ] return codeExtensions.contains(self) } diff --git a/Sources/Infrastructure/KeychainManager.swift b/Sources/Infrastructure/KeychainManager.swift index 94c83aa..231ff98 100644 --- a/Sources/Infrastructure/KeychainManager.swift +++ b/Sources/Infrastructure/KeychainManager.swift @@ -21,7 +21,7 @@ class KeychainManager { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, - kSecValueData as String: data + kSecValueData as String: data, ] SecItemAdd(query as CFDictionary, nil) @@ -32,7 +32,7 @@ class KeychainManager { kSecClass as String: kSecClassGenericPassword, kSecAttrAccount as String: key, kSecReturnData as String: true, - kSecMatchLimit as String: kSecMatchLimitOne + kSecMatchLimit as String: kSecMatchLimitOne, ] var item: CFTypeRef? @@ -45,7 +45,7 @@ class KeychainManager { func delete(_ key: String) { let query: [String: Any] = [ kSecClass as String: kSecClassGenericPassword, - kSecAttrAccount as String: key + kSecAttrAccount as String: key, ] SecItemDelete(query as CFDictionary) diff --git a/Sources/Infrastructure/TokenStorage.swift b/Sources/Infrastructure/TokenStorage.swift index 1a1a1c4..55fa7f7 100644 --- a/Sources/Infrastructure/TokenStorage.swift +++ b/Sources/Infrastructure/TokenStorage.swift @@ -14,7 +14,8 @@ import VoltaserveCore extension KeychainManager { func saveToken(_ token: VOToken.Value, forKey key: String) { if let data = try? JSONEncoder().encode(token), - let serialized = String(data: data, encoding: .utf8) { + let serialized = String(data: data, encoding: .utf8) + { saveString(serialized, for: key) } } diff --git a/Sources/Library/Modifiers/Button.swift b/Sources/Library/Modifiers/Button.swift index cf54b5c..ff21427 100644 --- a/Sources/Library/Modifiers/Button.swift +++ b/Sources/Library/Modifiers/Button.swift @@ -74,12 +74,15 @@ extension View { modifier(VOButton(color: .blue500, width: width, isDisabled: isDisabled)) } - func voSecondaryButton(colorScheme: ColorScheme, width: CGFloat? = nil, isDisabled: Bool = false) -> some View { - modifier(VOButton( - color: colorScheme == .dark ? .gray700 : .gray200, - width: width, - isDisabled: isDisabled - )) + func voSecondaryButton( + colorScheme: ColorScheme, width: CGFloat? = nil, isDisabled: Bool = false + ) -> some View { + modifier( + VOButton( + color: colorScheme == .dark ? .gray700 : .gray200, + width: width, + isDisabled: isDisabled + )) } } @@ -87,15 +90,18 @@ extension View { @Previewable @Environment(\.colorScheme) var colorScheme VStack { - Button {} label: { + Button { + } label: { VOButtonLabel("Lorem Ipsum") } .voPrimaryButton(width: 60) - Button {} label: { + Button { + } label: { VOButtonLabel("Lorem Ipsum", isLoading: true) } .voSecondaryButton(colorScheme: colorScheme, width: 200) - Button {} label: { + Button { + } label: { VOButtonLabel("Dolor Sit Amet") } .voButton(color: .red300) diff --git a/Sources/Library/Modifiers/ErrorAlert.swift b/Sources/Library/Modifiers/ErrorAlert.swift index 6e5600c..ff2a96d 100644 --- a/Sources/Library/Modifiers/ErrorAlert.swift +++ b/Sources/Library/Modifiers/ErrorAlert.swift @@ -36,7 +36,9 @@ struct VOErrorAlert: ViewModifier { } extension View { - func voErrorAlert(isPresented: Binding, title: String? = nil, message: String? = nil) -> some View { + func voErrorAlert(isPresented: Binding, title: String? = nil, message: String? = nil) + -> some View + { modifier(VOErrorAlert(isPresented: isPresented, title: title, message: message)) } } diff --git a/Sources/Library/Modifiers/ErrorSheet.swift b/Sources/Library/Modifiers/ErrorSheet.swift index e2dbd6f..4e56a2d 100644 --- a/Sources/Library/Modifiers/ErrorSheet.swift +++ b/Sources/Library/Modifiers/ErrorSheet.swift @@ -63,6 +63,7 @@ extension View { .voErrorSheet( isPresented: $showLongError, // swiftlint:disable:next line_length - message: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + message: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." ) } diff --git a/Sources/Library/Modifiers/FormHintLabel.swift b/Sources/Library/Modifiers/FormHintLabel.swift index c1e2306..0aefdf9 100644 --- a/Sources/Library/Modifiers/FormHintLabel.swift +++ b/Sources/Library/Modifiers/FormHintLabel.swift @@ -28,7 +28,8 @@ extension View { } #Preview { - Button {} label: { + Button { + } label: { Text("Lorem ipsum") .voFormHintLabel() } diff --git a/Sources/Library/Modifiers/WarningSheet.swift b/Sources/Library/Modifiers/WarningSheet.swift index c9870a3..0e261fe 100644 --- a/Sources/Library/Modifiers/WarningSheet.swift +++ b/Sources/Library/Modifiers/WarningSheet.swift @@ -63,6 +63,7 @@ extension View { .voWarningSheet( isPresented: $showLongWarning, // swiftlint:disable:next line_length - message: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + message: + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." ) } diff --git a/Sources/Library/Views/Avatar.swift b/Sources/Library/Views/Avatar.swift index 0fb5dae..ce21d34 100644 --- a/Sources/Library/Views/Avatar.swift +++ b/Sources/Library/Views/Avatar.swift @@ -51,7 +51,7 @@ struct VOAvatar: View { } var color = "" - for index in 0 ..< 3 { + for index in 0..<3 { let value = (hash >> (index * 8)) & 0xFF color += String(format: "%02x", value) } diff --git a/Sources/Library/Views/ButtonLabel.swift b/Sources/Library/Views/ButtonLabel.swift index b1796ac..16d22d9 100644 --- a/Sources/Library/Views/ButtonLabel.swift +++ b/Sources/Library/Views/ButtonLabel.swift @@ -16,7 +16,10 @@ struct VOButtonLabel: View { private let isLoading: Bool private let progressViewTint: Color - init(_ text: String, systemImage: String? = nil, isLoading: Bool = false, progressViewTint: Color = .primary) { + init( + _ text: String, systemImage: String? = nil, isLoading: Bool = false, + progressViewTint: Color = .primary + ) { self.text = text self.systemImage = systemImage self.isLoading = isLoading diff --git a/Sources/Library/Views/ColorBadge.swift b/Sources/Library/Views/ColorBadge.swift index fa0e6b5..5045114 100644 --- a/Sources/Library/Views/ColorBadge.swift +++ b/Sources/Library/Views/ColorBadge.swift @@ -23,7 +23,8 @@ struct VOColorBadge: View { var body: some View { if style == .fill { - } else if style == .outline {} + } else if style == .outline { + } Text(text) .font(.footnote) .padding(.horizontal) diff --git a/Sources/Library/Views/ErrorMessage.swift b/Sources/Library/Views/ErrorMessage.swift index cfd0b44..3d03c6e 100644 --- a/Sources/Library/Views/ErrorMessage.swift +++ b/Sources/Library/Views/ErrorMessage.swift @@ -37,7 +37,9 @@ struct VOErrorMessage: View { VStack(spacing: VOMetrics.spacing2Xl) { VOErrorMessage("Lorem ipsum dolor sit amet.") // swiftlint:disable:next line_length - VOErrorMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") + VOErrorMessage( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ) } .padding() } diff --git a/Sources/Library/Views/FormButtonLabel.swift b/Sources/Library/Views/FormButtonLabel.swift index ed14bb3..03bec72 100644 --- a/Sources/Library/Views/FormButtonLabel.swift +++ b/Sources/Library/Views/FormButtonLabel.swift @@ -32,7 +32,8 @@ struct VOFormButtonLabel: View { #Preview { Form { - Button {} label: { + Button { + } label: { VOFormButtonLabel("Lorem Ipsum", isLoading: true) } .disabled(true) diff --git a/Sources/Library/Views/WarningMessage.swift b/Sources/Library/Views/WarningMessage.swift index b6d6642..c868159 100644 --- a/Sources/Library/Views/WarningMessage.swift +++ b/Sources/Library/Views/WarningMessage.swift @@ -37,7 +37,9 @@ struct VOWarningMessage: View { VStack(spacing: VOMetrics.spacing2Xl) { VOWarningMessage("Lorem ipsum dolor sit amet.") // swiftlint:disable:next line_length - VOWarningMessage("Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.") + VOWarningMessage( + "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua." + ) } .padding() } diff --git a/Sources/Screens/Account/AccountEditEmail.swift b/Sources/Screens/Account/AccountEditEmail.swift index 5f78c96..ea4f458 100644 --- a/Sources/Screens/Account/AccountEditEmail.swift +++ b/Sources/Screens/Account/AccountEditEmail.swift @@ -99,7 +99,8 @@ struct AccountEditEmail: View, LoadStateProvider, FormValidatable, ErrorPresenta func isValid() -> Bool { if let identityUser = accountStore.identityUser { - return !normalizedValue.isEmpty && normalizedValue != (identityUser.pendingEmail ?? identityUser.email) + return !normalizedValue.isEmpty + && normalizedValue != (identityUser.pendingEmail ?? identityUser.email) } return false } diff --git a/Sources/Screens/Account/AccountOverview.swift b/Sources/Screens/Account/AccountOverview.swift index 31cd618..1586b06 100644 --- a/Sources/Screens/Account/AccountOverview.swift +++ b/Sources/Screens/Account/AccountOverview.swift @@ -11,7 +11,8 @@ import SwiftUI import VoltaserveCore -struct AccountOverview: View, ViewDataProvider, LoadStateProvider, TimerLifecycle, TokenDistributing { +struct AccountOverview: View, ViewDataProvider, LoadStateProvider, TimerLifecycle, TokenDistributing +{ @EnvironmentObject private var tokenStore: TokenStore @StateObject private var accountStore = AccountStore() @StateObject private var invitationStore = InvitationStore() @@ -42,23 +43,29 @@ struct AccountOverview: View, ViewDataProvider, LoadStateProvider, TimerLifecycl VStack(alignment: .leading) { if let storageUsage = accountStore.storageUsage { // swiftlint:disable:next line_length - Text("\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used") + Text( + "\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used" + ) ProgressView(value: Double(storageUsage.percentage) / 100.0) } } } Section { - NavigationLink(destination: AccountSettings(accountStore: accountStore) { - dismiss() - performSignOut() - }) { + NavigationLink( + destination: AccountSettings(accountStore: accountStore) { + dismiss() + performSignOut() + } + ) { Label("Settings", systemImage: "gear") } NavigationLink(destination: InvitationIncomingList()) { HStack { Label("Invitations", systemImage: "paperplane") Spacer() - if let incomingCount = invitationStore.incomingCount, incomingCount > 0 { + if let incomingCount = invitationStore.incomingCount, + incomingCount > 0 + { VONumberBadge(incomingCount) } } @@ -110,15 +117,13 @@ struct AccountOverview: View, ViewDataProvider, LoadStateProvider, TimerLifecycl // MARK: - LoadStateProvider var isLoading: Bool { - accountStore.identityUserIsLoading || - accountStore.storageUsageIsLoading || - invitationStore.incomingCountIsLoading + accountStore.identityUserIsLoading || accountStore.storageUsageIsLoading + || invitationStore.incomingCountIsLoading } var error: String? { - accountStore.identityUserError ?? - accountStore.storageUsageError ?? - invitationStore.incomingCountError + accountStore.identityUserError ?? accountStore.storageUsageError + ?? invitationStore.incomingCountError } // MARK: - ViewDataProvider diff --git a/Sources/Screens/Account/AccountSettings.swift b/Sources/Screens/Account/AccountSettings.swift index 292ceb7..b7809fc 100644 --- a/Sources/Screens/Account/AccountSettings.swift +++ b/Sources/Screens/Account/AccountSettings.swift @@ -35,7 +35,8 @@ struct AccountSettings: View, ViewDataProvider, LoadStateProvider, ErrorPresenta } else if let identityUser = accountStore.identityUser { Form { Section(header: VOSectionHeader("Basics")) { - NavigationLink(destination: AccountEditFullName(accountStore: accountStore)) { + NavigationLink(destination: AccountEditFullName(accountStore: accountStore)) + { HStack { Text("Full name") Spacer() @@ -68,7 +69,8 @@ struct AccountSettings: View, ViewDataProvider, LoadStateProvider, ErrorPresenta } .font(.footnote) } - NavigationLink(destination: AccountEditPassword(accountStore: accountStore)) { + NavigationLink(destination: AccountEditPassword(accountStore: accountStore)) + { HStack { Text("Password") Spacer() @@ -90,7 +92,9 @@ struct AccountSettings: View, ViewDataProvider, LoadStateProvider, ErrorPresenta VOFormButtonLabel("Delete Account", isLoading: isDeleting) } .disabled(isDeleting) - .confirmationDialog("Delete Account", isPresented: $deleteConfirmationIsPresented) { + .confirmationDialog( + "Delete Account", isPresented: $deleteConfirmationIsPresented + ) { Button("Delete Permanently", role: .destructive) { performDelete() } @@ -100,7 +104,8 @@ struct AccountSettings: View, ViewDataProvider, LoadStateProvider, ErrorPresenta .confirmationDialog( "Missing Password Confirmation", isPresented: $deleteNoticeIsPresented - ) {} message: { + ) { + } message: { Text("You need to enter your password to confirm the account deletion.") } } diff --git a/Sources/Screens/Account/AccountStore.swift b/Sources/Screens/Account/AccountStore.swift index 5eb196f..63dbaec 100644 --- a/Sources/Screens/Account/AccountStore.swift +++ b/Sources/Screens/Account/AccountStore.swift @@ -109,7 +109,8 @@ class AccountStore: ObservableObject { } func updatePassword(current: String, new: String) async throws -> VOIdentityUser.Entity? { - try await identityUserClient?.updatePassword(.init(currentPassword: current, newPassword: new)) + try await identityUserClient?.updatePassword( + .init(currentPassword: current, newPassword: new)) } func deleteAccount(password: String) async throws { diff --git a/Sources/Screens/Browser/BrowserList.swift b/Sources/Screens/Browser/BrowserList.swift index ca23460..0eeed03 100644 --- a/Sources/Screens/Browser/BrowserList.swift +++ b/Sources/Screens/Browser/BrowserList.swift @@ -12,7 +12,9 @@ import Combine import SwiftUI import VoltaserveCore -struct BrowserList: View, LoadStateProvider, ViewDataProvider, TimerLifecycle, TokenDistributing, ListItemScrollable { +struct BrowserList: View, LoadStateProvider, ViewDataProvider, TimerLifecycle, TokenDistributing, + ListItemScrollable +{ @EnvironmentObject private var tokenStore: TokenStore @ObservedObject private var workspaceStore: WorkspaceStore @StateObject private var browserStore = BrowserStore() diff --git a/Sources/Screens/Browser/BrowserStore.swift b/Sources/Screens/Browser/BrowserStore.swift index 521a23b..c43c389 100644 --- a/Sources/Screens/Browser/BrowserStore.swift +++ b/Sources/Screens/Browser/BrowserStore.swift @@ -72,12 +72,18 @@ class BrowserStore: ObservableObject { } } - private func fetchProbe(_ id: String, size: Int = Constants.pageSize) async throws -> VOFile.Probe? { - try await fileClient?.fetchProbe(id, options: .init(query: query, size: size, type: .folder)) + private func fetchProbe(_ id: String, size: Int = Constants.pageSize) async throws -> VOFile + .Probe? + { + try await fileClient?.fetchProbe( + id, options: .init(query: query, size: size, type: .folder)) } - private func fetchList(_ id: String, page: Int = 1, size: Int = Constants.pageSize) async throws -> VOFile.List? { - try await fileClient?.fetchList(id, options: .init(query: query, page: page, size: size, type: .folder)) + private func fetchList(_ id: String, page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOFile.List? + { + try await fileClient?.fetchList( + id, options: .init(query: query, page: page, size: size, type: .folder)) } func fetchNextPage(replace: Bool = false) { @@ -161,7 +167,8 @@ class BrowserStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/File/FileDownload.swift b/Sources/Screens/File/FileDownload.swift index 4b16e5a..2bb4868 100644 --- a/Sources/Screens/File/FileDownload.swift +++ b/Sources/Screens/File/FileDownload.swift @@ -77,8 +77,10 @@ struct FileDownload: View { urls.removeAll() for file in fileStore.selectionFiles { if let snapshot = file.snapshot, - let fileExtension = snapshot.original.fileExtension, - let url = fileStore.urlForOriginal(file.id, fileExtension: String(fileExtension.dropFirst())) { + let fileExtension = snapshot.original.fileExtension, + let url = fileStore.urlForOriginal( + file.id, fileExtension: String(fileExtension.dropFirst())) + { dispatchGroup.enter() URLSession.shared.downloadTask(with: url) { localURL, _, error in if let localURL, error == nil { diff --git a/Sources/Screens/File/FileGrid.swift b/Sources/Screens/File/FileGrid.swift index 7dc6d83..1c15bab 100644 --- a/Sources/Screens/File/FileGrid.swift +++ b/Sources/Screens/File/FileGrid.swift @@ -25,9 +25,10 @@ struct FileGrid: View, ListItemScrollable { if let entities = fileStore.entities { GeometryReader { geometry in let columns = Array( - repeating: GridItem(.fixed(FileCellMetrics.cellSize.width), spacing: VOMetrics.spacing), - count: Int(geometry.size.width / FileCellMetrics.cellSize.width) + - (UIDevice.current.userInterfaceIdiom == .pad ? -1 : 0) + repeating: GridItem( + .fixed(FileCellMetrics.cellSize.width), spacing: VOMetrics.spacing), + count: Int(geometry.size.width / FileCellMetrics.cellSize.width) + + (UIDevice.current.userInterfaceIdiom == .pad ? -1 : 0) ) ScrollView { LazyVGrid(columns: columns, spacing: VOMetrics.spacing) { diff --git a/Sources/Screens/File/FileInfo.swift b/Sources/Screens/File/FileInfo.swift index d0ba12f..45ce95e 100644 --- a/Sources/Screens/File/FileInfo.swift +++ b/Sources/Screens/File/FileInfo.swift @@ -104,7 +104,9 @@ struct FileInfo: View, ViewDataProvider, LoadStateProvider, TimerLifecycle, Toke VStack(alignment: .leading) { if let storageUsage = fileStore.storageUsage { // swiftlint:disable:next line_length - Text("\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used") + Text( + "\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used" + ) ProgressView(value: Double(storageUsage.percentage) / 100.0) } else { Text("Calculating…") diff --git a/Sources/Screens/File/FileRename.swift b/Sources/Screens/File/FileRename.swift index c2a5347..ad97e3c 100644 --- a/Sources/Screens/File/FileRename.swift +++ b/Sources/Screens/File/FileRename.swift @@ -17,7 +17,8 @@ struct FileRename: View, TimerLifecycle, TokenDistributing, FormValidatable, - ErrorPresentable { + ErrorPresentable +{ @EnvironmentObject private var tokenStore: TokenStore @StateObject private var fileStore = FileStore() @Environment(\.dismiss) private var dismiss diff --git a/Sources/Screens/File/FileStore.swift b/Sources/Screens/File/FileStore.swift index c0a64a5..128db01 100644 --- a/Sources/Screens/File/FileStore.swift +++ b/Sources/Screens/File/FileStore.swift @@ -127,11 +127,15 @@ class FileStore: ObservableObject { } } - private func fetchProbe(_ id: String, size: Int = Constants.pageSize) async throws -> VOFile.Probe? { + private func fetchProbe(_ id: String, size: Int = Constants.pageSize) async throws -> VOFile + .Probe? + { try await fileClient?.fetchProbe(id, options: .init(size: size)) } - private func fetchList(_ id: String, page: Int = 1, size: Int = Constants.pageSize) async throws -> VOFile.List? { + private func fetchList(_ id: String, page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOFile.List? + { try await fileClient?.fetchList(id, options: .init(query: query, page: page, size: size)) } @@ -242,8 +246,11 @@ class FileStore: ObservableObject { // MARK: - Update - func createFolder(name: String, workspaceID: String, parentID: String) async throws -> VOFile.Entity? { - try await fileClient?.createFolder(.init(workspaceID: workspaceID, parentID: parentID, name: name)) + func createFolder(name: String, workspaceID: String, parentID: String) async throws -> VOFile + .Entity? + { + try await fileClient?.createFolder( + .init(workspaceID: workspaceID, parentID: parentID, name: name)) } func patchName(_ id: String, name: String) async throws -> VOFile.Entity? { @@ -265,12 +272,13 @@ class FileStore: ObservableObject { func upload(_ url: URL, workspaceID: String) async throws -> VOFile.Entity? { guard let file else { return nil } if let data = try? Data(contentsOf: url) { - return try await fileClient?.createFile(.init( - workspaceID: workspaceID, - parentID: file.id, - name: url.lastPathComponent, - data: data - )) + return try await fileClient?.createFile( + .init( + workspaceID: workspaceID, + parentID: file.id, + name: url.lastPathComponent, + data: data + )) } return nil } @@ -327,7 +335,8 @@ class FileStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id @@ -390,28 +399,32 @@ class FileStore: ObservableObject { func isOwnerInSelection(_ selection: Set) -> Bool { guard let entities else { return false } - return entities + return + entities .filter { selection.contains($0.id) } .allSatisfy { $0.permission.ge(.owner) } } func isEditorInSelection(_ selection: Set) -> Bool { guard let entities else { return false } - return entities + return + entities .filter { selection.contains($0.id) } .allSatisfy { $0.permission.ge(.editor) } } func isViewerInSelection(_ selection: Set) -> Bool { guard let entities else { return false } - return entities + return + entities .filter { selection.contains($0.id) } .allSatisfy { $0.permission.ge(.viewer) } } func isFilesInSelection(_ selection: Set) -> Bool { guard let entities else { return false } - return entities + return + entities .filter { selection.contains($0.id) } .allSatisfy { $0.type == .file } } @@ -419,22 +432,17 @@ class FileStore: ObservableObject { func isInsightsAuthorized(_ file: VOFile.Entity) -> Bool { guard let snapshot = file.snapshot else { return false } guard let fileExtension = snapshot.original.fileExtension else { return false } - return file.type == .file && - !(file.snapshot?.task?.isPending ?? false) && - (fileExtension.isPDF() || - fileExtension.isMicrosoftOffice() || - fileExtension.isOpenOffice() || - fileExtension.isImage()) && - ((file.permission.ge(.viewer) && snapshot.entities != nil) || - file.permission.ge(.editor)) + return file.type == .file && !(file.snapshot?.task?.isPending ?? false) + && (fileExtension.isPDF() || fileExtension.isMicrosoftOffice() + || fileExtension.isOpenOffice() || fileExtension.isImage()) + && ((file.permission.ge(.viewer) && snapshot.entities != nil) + || file.permission.ge(.editor)) } func isMosaicAuthorized(_ file: VOFile.Entity) -> Bool { guard let snapshot = file.snapshot else { return false } guard let fileExtension = snapshot.original.fileExtension else { return false } - return file.type == .file && - !(snapshot.task?.isPending ?? false) && - fileExtension.isImage() + return file.type == .file && !(snapshot.task?.isPending ?? false) && fileExtension.isImage() } func isSharingAuthorized(_ file: VOFile.Entity) -> Bool { @@ -498,10 +506,8 @@ class FileStore: ObservableObject { } func isManagementAuthorized(_ file: VOFile.Entity) -> Bool { - isSharingAuthorized(file) || - isSnapshotsAuthorized(file) || - isUploadAuthorized(file) || - isDownloadAuthorized(file) + isSharingAuthorized(file) || isSnapshotsAuthorized(file) || isUploadAuthorized(file) + || isDownloadAuthorized(file) } func isOpenAuthorized(_ file: VOFile.Entity) -> Bool { diff --git a/Sources/Screens/File/Icon/File+Icon.swift b/Sources/Screens/File/Icon/File+Icon.swift index fdc3888..8d0702b 100644 --- a/Sources/Screens/File/Icon/File+Icon.swift +++ b/Sources/Screens/File/Icon/File+Icon.swift @@ -18,43 +18,44 @@ extension VOFile.Entity { guard let fileExtension = snapshot.original.fileExtension else { return "" } let hasThumbnail = snapshot.thumbnail != nil - var image = if fileExtension.isImage() { - "icon-image" - } else if fileExtension.isPDF() { - "icon-pdf" - } else if fileExtension.isText() { - "icon-text" - } else if fileExtension.isRichText() { - "icon-rich-text" - } else if fileExtension.isWord() { - "icon-word" - } else if fileExtension.isPowerPoint() { - "icon-power-point" - } else if fileExtension.isExcel() { - "icon-spreadsheet" - } else if fileExtension.isDocument() { - "icon-word" - } else if fileExtension.isSpreadsheet() { - "icon-spreadsheet" - } else if fileExtension.isSlides() { - "icon-power-point" - } else if fileExtension.isVideo(), hasThumbnail { - "icon-video" - } else if fileExtension.isAudio(), !hasThumbnail { - "icon-audio" - } else if fileExtension.isArchive() { - "icon-archive" - } else if fileExtension.isFont() { - "icon-file" - } else if fileExtension.isCode() { - "icon-code" - } else if fileExtension.isCSV() { - "icon-csv" - } else if fileExtension.isGLB() { - "icon-model" - } else { - "icon-file" - } + var image = + if fileExtension.isImage() { + "icon-image" + } else if fileExtension.isPDF() { + "icon-pdf" + } else if fileExtension.isText() { + "icon-text" + } else if fileExtension.isRichText() { + "icon-rich-text" + } else if fileExtension.isWord() { + "icon-word" + } else if fileExtension.isPowerPoint() { + "icon-power-point" + } else if fileExtension.isExcel() { + "icon-spreadsheet" + } else if fileExtension.isDocument() { + "icon-word" + } else if fileExtension.isSpreadsheet() { + "icon-spreadsheet" + } else if fileExtension.isSlides() { + "icon-power-point" + } else if fileExtension.isVideo(), hasThumbnail { + "icon-video" + } else if fileExtension.isAudio(), !hasThumbnail { + "icon-audio" + } else if fileExtension.isArchive() { + "icon-archive" + } else if fileExtension.isFont() { + "icon-file" + } else if fileExtension.isCode() { + "icon-code" + } else if fileExtension.isCSV() { + "icon-csv" + } else if fileExtension.isGLB() { + "icon-model" + } else { + "icon-file" + } if colorScheme == .dark { image = "dark-" + image diff --git a/Sources/Screens/File/Icon/FileCell.swift b/Sources/Screens/File/Icon/FileCell.swift index 9b10ae1..903e46a 100644 --- a/Sources/Screens/File/Icon/FileCell.swift +++ b/Sources/Screens/File/Icon/FileCell.swift @@ -25,9 +25,11 @@ struct FileCell: View { VStack(spacing: VOMetrics.spacing) { if file.type == .file { if let snapshot = file.snapshot, - let thumbnail = snapshot.thumbnail, - let fileExtension = thumbnail.fileExtension, - let url = fileStore.urlForThumbnail(file.id, fileExtension: String(fileExtension.dropFirst())) { + let thumbnail = snapshot.thumbnail, + let fileExtension = thumbnail.fileExtension, + let url = fileStore.urlForThumbnail( + file.id, fileExtension: String(fileExtension.dropFirst())) + { FileCellThumbnail(url: url, file: file, fileStore: fileStore) { fileIcon } @@ -58,17 +60,22 @@ struct FileCell: View { .resizable() .aspectRatio(contentMode: .fit) .fileCellAdornments(file) - .frame(width: FileCellMetrics.iconSize.width, height: FileCellMetrics.iconSize.height) + .frame( + width: FileCellMetrics.iconSize.width, + height: FileCellMetrics.iconSize.height) } .frame( width: FileCellMetrics.iconSize.width + VOMetrics.spacingLg, height: FileCellMetrics.iconSize.height + VOMetrics.spacing2Xl ) .background(colorScheme == .light ? .white : .clear) - .contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm)) + .contentShape( + .contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm) + ) .fileActions(file, fileStore: fileStore) } - .frame(maxWidth: FileCellMetrics.frameSize.width, maxHeight: FileCellMetrics.frameSize.height) + .frame( + maxWidth: FileCellMetrics.frameSize.width, maxHeight: FileCellMetrics.frameSize.height) } private var folderIcon: some View { @@ -78,16 +85,21 @@ struct FileCell: View { .resizable() .aspectRatio(contentMode: .fit) .fileCellAdornments(file) - .frame(width: FileCellMetrics.iconSize.width, height: FileCellMetrics.iconSize.height) + .frame( + width: FileCellMetrics.iconSize.width, + height: FileCellMetrics.iconSize.height) } .frame( width: FileCellMetrics.iconSize.width + VOMetrics.spacing2Xl, height: FileCellMetrics.iconSize.height + VOMetrics.spacingLg ) .background(colorScheme == .light ? .white : .clear) - .contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm)) + .contentShape( + .contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm) + ) .fileActions(file, fileStore: fileStore) } - .frame(maxWidth: FileCellMetrics.frameSize.width, maxHeight: FileCellMetrics.frameSize.height) + .frame( + maxWidth: FileCellMetrics.frameSize.width, maxHeight: FileCellMetrics.frameSize.height) } } diff --git a/Sources/Screens/File/Icon/FileCellThumbnail.swift b/Sources/Screens/File/Icon/FileCellThumbnail.swift index bef779f..5e625d0 100644 --- a/Sources/Screens/File/Icon/FileCellThumbnail.swift +++ b/Sources/Screens/File/Icon/FileCellThumbnail.swift @@ -18,7 +18,10 @@ struct FileCellThumbnail: View { private let fallback: () -> FallbackContent private let file: VOFile.Entity - init(url: URL, file: VOFile.Entity, fileStore: FileStore, @ViewBuilder fallback: @escaping () -> FallbackContent) { + init( + url: URL, file: VOFile.Entity, fileStore: FileStore, + @ViewBuilder fallback: @escaping () -> FallbackContent + ) { self.url = url self.fallback = fallback self.file = file @@ -31,7 +34,9 @@ struct FileCellThumbnail: View { .resizable() .aspectRatio(contentMode: .fit) .clipShape(RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm)) - .contentShape(.contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm)) + .contentShape( + .contextMenuPreview, RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm) + ) .fileActions(file, fileStore: fileStore) .overlay { RoundedRectangle(cornerRadius: VOMetrics.borderRadiusSm) @@ -39,14 +44,18 @@ struct FileCellThumbnail: View { } .fileCellAdornments(file) .overlay { - if let fileExtension = file.snapshot?.original.fileExtension, fileExtension.isVideo() { + if let fileExtension = file.snapshot?.original.fileExtension, + fileExtension.isVideo() + { Image(systemName: "play.fill") .foregroundStyle(.white) .font(.largeTitle) .opacity(0.5) } } - .frame(maxWidth: FileCellMetrics.frameSize.width, maxHeight: FileCellMetrics.frameSize.height) + .frame( + maxWidth: FileCellMetrics.frameSize.width, + maxHeight: FileCellMetrics.frameSize.height) } placeholder: { fallback() } diff --git a/Sources/Screens/File/Menu/FileActions.swift b/Sources/Screens/File/Menu/FileActions.swift index 07088c3..8e881d1 100644 --- a/Sources/Screens/File/Menu/FileActions.swift +++ b/Sources/Screens/File/Menu/FileActions.swift @@ -57,8 +57,10 @@ struct FileActions: ViewModifier { }, onOpen: { if let snapshot = file.snapshot, - let fileExtension = snapshot.original.fileExtension, - let url = fileStore.urlForOriginal(file.id, fileExtension: String(fileExtension.dropFirst())) { + let fileExtension = snapshot.original.fileExtension, + let url = fileStore.urlForOriginal( + file.id, fileExtension: String(fileExtension.dropFirst())) + { UIApplication.shared.open(url) } }, diff --git a/Sources/Screens/File/Menu/FileContextMenu.swift b/Sources/Screens/File/Menu/FileContextMenu.swift index 0ba8640..871a263 100644 --- a/Sources/Screens/File/Menu/FileContextMenu.swift +++ b/Sources/Screens/File/Menu/FileContextMenu.swift @@ -195,21 +195,22 @@ extension View { onOpen: (() -> Void)? = nil, onInfo: (() -> Void)? = nil ) -> some View { - modifier(FileContextMenu( - file, - fileStore: fileStore, - onInsights: onInsights, - onMosaic: onMosaic, - onSharing: onSharing, - onSnapshots: onSnapshots, - onUpload: onUpload, - onDownload: onDownload, - onDelete: onDelete, - onRename: onRename, - onMove: onMove, - onCopy: onCopy, - onOpen: onOpen, - onInfo: onInfo - )) + modifier( + FileContextMenu( + file, + fileStore: fileStore, + onInsights: onInsights, + onMosaic: onMosaic, + onSharing: onSharing, + onSnapshots: onSnapshots, + onUpload: onUpload, + onDownload: onDownload, + onDelete: onDelete, + onRename: onRename, + onMove: onMove, + onCopy: onCopy, + onOpen: onOpen, + onInfo: onInfo + )) } } diff --git a/Sources/Screens/File/Menu/FileMenu.swift b/Sources/Screens/File/Menu/FileMenu.swift index 86133b1..3c47d22 100644 --- a/Sources/Screens/File/Menu/FileMenu.swift +++ b/Sources/Screens/File/Menu/FileMenu.swift @@ -60,8 +60,9 @@ struct FileMenu: View { Label("Download", systemImage: "square.and.arrow.down") } } - if fileStore.isSharingAuthorized(fileStore.selection) || - fileStore.isDownloadAuthorized(fileStore.selection) { + if fileStore.isSharingAuthorized(fileStore.selection) + || fileStore.isDownloadAuthorized(fileStore.selection) + { Divider() } if fileStore.isDeleteAuthorized(fileStore.selection) { diff --git a/Sources/Screens/File/Sheet/FileSheetCopy.swift b/Sources/Screens/File/Sheet/FileSheetCopy.swift index 9077061..fbd7557 100644 --- a/Sources/Screens/File/Sheet/FileSheetCopy.swift +++ b/Sources/Screens/File/Sheet/FileSheetCopy.swift @@ -25,7 +25,9 @@ struct FileSheetCopy: ViewModifier { .sheet(isPresented: $fileStore.browserForCopyIsPresented) { NavigationStack { if let workspace = workspaceStore.current { - BrowserOverview(workspaceStore: workspaceStore, confirmLabelText: "Copy Here") { id in + BrowserOverview( + workspaceStore: workspaceStore, confirmLabelText: "Copy Here" + ) { id in destinationID = id fileStore.copyIsPresented = true } diff --git a/Sources/Screens/File/Sheet/FileSheetCreateFolder.swift b/Sources/Screens/File/Sheet/FileSheetCreateFolder.swift index 9a55a82..5335d7e 100644 --- a/Sources/Screens/File/Sheet/FileSheetCreateFolder.swift +++ b/Sources/Screens/File/Sheet/FileSheetCreateFolder.swift @@ -23,7 +23,8 @@ struct FileSheetCreateFolder: ViewModifier { content .sheet(isPresented: $fileStore.createFolderIsPresented) { if let parent = fileStore.file, let workspace = workspaceStore.current { - FolderCreate(parentID: parent.id, workspaceId: workspace.id, fileStore: fileStore) + FolderCreate( + parentID: parent.id, workspaceId: workspace.id, fileStore: fileStore) } } } diff --git a/Sources/Screens/File/Sheet/FileSheetDownload.swift b/Sources/Screens/File/Sheet/FileSheetDownload.swift index 641fef5..803916b 100644 --- a/Sources/Screens/File/Sheet/FileSheetDownload.swift +++ b/Sources/Screens/File/Sheet/FileSheetDownload.swift @@ -28,7 +28,9 @@ struct FileSheetDownload: ViewModifier { } } } - .sheet(isPresented: $fileStore.downloadDocumentPickerIsPresented, onDismiss: handleDismiss) { + .sheet( + isPresented: $fileStore.downloadDocumentPickerIsPresented, onDismiss: handleDismiss + ) { if let pickerURLs { FileDownloadPicker( sourceURLs: pickerURLs, diff --git a/Sources/Screens/File/Sheet/FileSheetMove.swift b/Sources/Screens/File/Sheet/FileSheetMove.swift index 59245ce..4c07fed 100644 --- a/Sources/Screens/File/Sheet/FileSheetMove.swift +++ b/Sources/Screens/File/Sheet/FileSheetMove.swift @@ -25,7 +25,9 @@ struct FileSheetMove: ViewModifier { .sheet(isPresented: $fileStore.browserForMoveIsPresented) { if let workspace = workspaceStore.current { NavigationStack { - BrowserOverview(workspaceStore: workspaceStore, confirmLabelText: "Move Here") { id in + BrowserOverview( + workspaceStore: workspaceStore, confirmLabelText: "Move Here" + ) { id in destinationID = id fileStore.moveIsPresented = true } diff --git a/Sources/Screens/ForgotPassword/ForgotPassword.swift b/Sources/Screens/ForgotPassword/ForgotPassword.swift index d25043a..04a7199 100644 --- a/Sources/Screens/ForgotPassword/ForgotPassword.swift +++ b/Sources/Screens/ForgotPassword/ForgotPassword.swift @@ -27,10 +27,12 @@ struct ForgotPassword: View { VOLogo(isGlossy: true, size: .init(width: 100, height: 100)) Text("Forgot Password") .voHeading(fontSize: VOMetrics.headingFontSize) - Text("Please provide your account Email where we can send you the password recovery instructions.") - .voFormHintText() - .frame(width: VOMetrics.formWidth) - .multilineTextAlignment(.center) + Text( + "Please provide your account Email where we can send you the password recovery instructions." + ) + .voFormHintText() + .frame(width: VOMetrics.formWidth) + .multilineTextAlignment(.center) TextField("Email", text: $email) .voTextField(width: VOMetrics.formWidth) .textInputAutocapitalization(.never) diff --git a/Sources/Screens/Group/GroupRow.swift b/Sources/Screens/Group/GroupRow.swift index 74bf016..541cc07 100644 --- a/Sources/Screens/Group/GroupRow.swift +++ b/Sources/Screens/Group/GroupRow.swift @@ -38,16 +38,17 @@ struct GroupRow: View { } #Preview { - GroupRow(.init( - id: UUID().uuidString, - name: "My Group", - organization: .init( + GroupRow( + .init( id: UUID().uuidString, - name: "My Organization", + name: "My Group", + organization: .init( + id: UUID().uuidString, + name: "My Organization", + permission: .owner, + createTime: Date().ISO8601Format() + ), permission: .owner, createTime: Date().ISO8601Format() - ), - permission: .owner, - createTime: Date().ISO8601Format() - )) + )) } diff --git a/Sources/Screens/Group/GroupSettings.swift b/Sources/Screens/Group/GroupSettings.swift index 04a02a8..7f2ade8 100644 --- a/Sources/Screens/Group/GroupSettings.swift +++ b/Sources/Screens/Group/GroupSettings.swift @@ -35,7 +35,9 @@ struct GroupSettings: View { NavigationLink { GroupEditName(groupStore: groupStore) { updatedGroup in groupStore.current = updatedGroup - if let index = groupStore.entities?.firstIndex(where: { $0.id == updatedGroup.id }) { + if let index = groupStore.entities?.firstIndex(where: { + $0.id == updatedGroup.id + }) { groupStore.entities?[index] = updatedGroup } } diff --git a/Sources/Screens/Group/GroupStore.swift b/Sources/Screens/Group/GroupStore.swift index d4d2ae8..45b3c1d 100644 --- a/Sources/Screens/Group/GroupStore.swift +++ b/Sources/Screens/Group/GroupStore.swift @@ -58,33 +58,39 @@ class GroupStore: ObservableObject { private func fetchProbe(size: Int = Constants.pageSize) async throws -> VOGroup.Probe? { if let organizationID { - try await groupClient?.fetchProbe(.init( - query: query, - organizationID: organizationID, - size: size - )) + try await groupClient?.fetchProbe( + .init( + query: query, + organizationID: organizationID, + size: size + )) } else { - try await groupClient?.fetchProbe(.init( - query: query, - size: size - )) + try await groupClient?.fetchProbe( + .init( + query: query, + size: size + )) } } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOGroup.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOGroup + .List? + { if let organizationID { - try await groupClient?.fetchList(.init( - query: query, - organizationID: organizationID, - page: page, - size: size - )) + try await groupClient?.fetchList( + .init( + query: query, + organizationID: organizationID, + page: page, + size: size + )) } else { - try await groupClient?.fetchList(.init( - query: query, - page: page, - size: size - )) + try await groupClient?.fetchList( + .init( + query: query, + page: page, + size: size + )) } } @@ -189,7 +195,8 @@ class GroupStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Insights/InsightsCreate.swift b/Sources/Screens/Insights/InsightsCreate.swift index 3aafd45..b534841 100644 --- a/Sources/Screens/Insights/InsightsCreate.swift +++ b/Sources/Screens/Insights/InsightsCreate.swift @@ -34,7 +34,9 @@ struct InsightsCreate: View { VStack { ScrollView { // swiftlint:disable:next line_length - Text("Select the language to use for collecting insights. During the process, text will be extracted using OCR (optical character recognition), and entities will be scanned using NER (named entity recognition).") + Text( + "Select the language to use for collecting insights. During the process, text will be extracted using OCR (optical character recognition), and entities will be scanned using NER (named entity recognition)." + ) } Picker("Language", selection: $language) { ForEach(languages, id: \.id) { language in diff --git a/Sources/Screens/Insights/InsightsSettings.swift b/Sources/Screens/Insights/InsightsSettings.swift index 65b4d76..937760c 100644 --- a/Sources/Screens/Insights/InsightsSettings.swift +++ b/Sources/Screens/Insights/InsightsSettings.swift @@ -38,9 +38,13 @@ struct InsightsSettings: View { Button { performPatch() } label: { - VOButtonLabel("Collect Insights", systemImage: "bolt", isLoading: isPatching) + VOButtonLabel( + "Collect Insights", systemImage: "bolt", + isLoading: isPatching) } - .voSecondaryButton(colorScheme: colorScheme, isDisabled: isProcessing || !canCreate) + .voSecondaryButton( + colorScheme: colorScheme, isDisabled: isProcessing || !canCreate + ) } .padding() } @@ -54,7 +58,9 @@ struct InsightsSettings: View { Button { performDelete() } label: { - VOButtonLabel("Delete Insights", systemImage: "trash", isLoading: isDeleting) + VOButtonLabel( + "Delete Insights", systemImage: "trash", + isLoading: isDeleting) } .voButton(color: .red400, isDisabled: isProcessing || !canDelete) } @@ -109,18 +115,16 @@ struct InsightsSettings: View { private var canCreate: Bool { if let info = insightsStore.info { - return !(file.snapshot?.task?.isPending ?? false) && - info.isOutdated && - file.permission.ge(.editor) + return !(file.snapshot?.task?.isPending ?? false) && info.isOutdated + && file.permission.ge(.editor) } return false } private var canDelete: Bool { if let info = insightsStore.info { - return !(file.snapshot?.task?.isPending ?? false) && - !info.isOutdated && - file.permission.ge(.owner) + return !(file.snapshot?.task?.isPending ?? false) && !info.isOutdated + && file.permission.ge(.owner) } return false } diff --git a/Sources/Screens/Insights/InsightsStore.swift b/Sources/Screens/Insights/InsightsStore.swift index a6e8071..21d0aac 100644 --- a/Sources/Screens/Insights/InsightsStore.swift +++ b/Sources/Screens/Insights/InsightsStore.swift @@ -91,7 +91,9 @@ class InsightsStore: ObservableObject { } } - private func fetchEntityProbe(size: Int = Constants.pageSize) async throws -> VOInsights.EntityProbe? { + private func fetchEntityProbe(size: Int = Constants.pageSize) async throws -> VOInsights + .EntityProbe? + { guard let fileID else { return nil } return try await insightsClient?.fetchEntityProbe( fileID, @@ -104,7 +106,9 @@ class InsightsStore: ObservableObject { ) } - private func fetchEntityList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOInsights.EntityList? { + private func fetchEntityList(page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOInsights.EntityList? + { guard let fileID else { return nil } return try await insightsClient?.fetchEntityList( fileID, @@ -178,7 +182,8 @@ class InsightsStore: ObservableObject { if entities == nil { entities = [] } - for newEntity in newEntities where !entities!.contains(where: { $0.text == newEntity.text }) { + for newEntity in newEntities where !entities!.contains(where: { $0.text == newEntity.text }) + { entities!.append(newEntity) } } @@ -210,7 +215,8 @@ class InsightsStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Invitation/InvitationOverview.swift b/Sources/Screens/Invitation/InvitationOverview.swift index ad08822..2d089dc 100644 --- a/Sources/Screens/Invitation/InvitationOverview.swift +++ b/Sources/Screens/Invitation/InvitationOverview.swift @@ -126,7 +126,8 @@ struct InvitationOverview: View { } } .disabled(isProcessing) - .confirmationDialog("Decline Invitation", isPresented: $showDeclineConfirmation) { + .confirmationDialog("Decline Invitation", isPresented: $showDeclineConfirmation) + { Button("Decline", role: .destructive) { performDecline() } diff --git a/Sources/Screens/Invitation/InvitationStore.swift b/Sources/Screens/Invitation/InvitationStore.swift index 82bcca8..f813420 100644 --- a/Sources/Screens/Invitation/InvitationStore.swift +++ b/Sources/Screens/Invitation/InvitationStore.swift @@ -39,15 +39,19 @@ class InvitationStore: ObservableObject { private func fetchProbe(size: Int = Constants.pageSize) async throws -> VOInvitation.Probe? { if let organizationID { - try await invitationClient?.fetchOutgoingProbe(.init(organizationID: organizationID, size: size)) + try await invitationClient?.fetchOutgoingProbe( + .init(organizationID: organizationID, size: size)) } else { try await invitationClient?.fetchIncomingProbe(.init(size: size)) } } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOInvitation.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOInvitation.List? + { if let organizationID { - try await invitationClient?.fetchOutgoingList(.init(organizationID: organizationID, page: page, size: size)) + try await invitationClient?.fetchOutgoingList( + .init(organizationID: organizationID, page: page, size: size)) } else { try await invitationClient?.fetchIncomingList(.init(page: page, size: size)) } @@ -118,7 +122,8 @@ class InvitationStore: ObservableObject { func create(emails: [String]) async throws -> [VOInvitation.Entity]? { guard let organizationID else { return nil } - return try await invitationClient?.create(.init(organizationID: organizationID, emails: emails)) + return try await invitationClient?.create( + .init(organizationID: organizationID, emails: emails)) } func accept(_ id: String) async throws { @@ -171,7 +176,8 @@ class InvitationStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Mosaic/MosaicCreate.swift b/Sources/Screens/Mosaic/MosaicCreate.swift index bdbbc78..22e7e57 100644 --- a/Sources/Screens/Mosaic/MosaicCreate.swift +++ b/Sources/Screens/Mosaic/MosaicCreate.swift @@ -32,7 +32,9 @@ struct MosaicCreate: View { VStack { ScrollView { // swiftlint:disable:next line_length - Text("Create a mosaic to enhance view performance of a large image by splitting it into smaller, manageable tiles. This makes browsing a high-resolution image faster and more efficient.") + Text( + "Create a mosaic to enhance view performance of a large image by splitting it into smaller, manageable tiles. This makes browsing a high-resolution image faster and more efficient." + ) } Button { performCreate() diff --git a/Sources/Screens/Mosaic/MosaicSettings.swift b/Sources/Screens/Mosaic/MosaicSettings.swift index 4dd6fdb..1f98e3b 100644 --- a/Sources/Screens/Mosaic/MosaicSettings.swift +++ b/Sources/Screens/Mosaic/MosaicSettings.swift @@ -38,9 +38,12 @@ struct MosaicSettings: View { Button { performCreate() } label: { - VOButtonLabel("Create Mosaic", systemImage: "bolt", isLoading: isCreating) + VOButtonLabel( + "Create Mosaic", systemImage: "bolt", isLoading: isCreating) } - .voSecondaryButton(colorScheme: colorScheme, isDisabled: isProcesssing || !canCreate) + .voSecondaryButton( + colorScheme: colorScheme, + isDisabled: isProcesssing || !canCreate) } .padding() } @@ -54,8 +57,10 @@ struct MosaicSettings: View { Button { performDelete() } label: { - VOButtonLabel("Delete Mosaic", systemImage: "trash", isLoading: isDeleting) - .foregroundStyle(Color.red400.textColor()) + VOButtonLabel( + "Delete Mosaic", systemImage: "trash", isLoading: isDeleting + ) + .foregroundStyle(Color.red400.textColor()) } .voButton(color: .red400, isDisabled: isProcesssing || !canDelete) } @@ -113,18 +118,16 @@ struct MosaicSettings: View { private var canCreate: Bool { if let info = mosaicStore.info { - return !(file.snapshot?.task?.isPending ?? false) && - info.isOutdated && - file.permission.ge(.editor) + return !(file.snapshot?.task?.isPending ?? false) && info.isOutdated + && file.permission.ge(.editor) } return false } private var canDelete: Bool { if let info = mosaicStore.info { - return !(file.snapshot?.task?.isPending ?? false) && - !info.isOutdated && - file.permission.ge(.owner) + return !(file.snapshot?.task?.isPending ?? false) && !info.isOutdated + && file.permission.ge(.owner) } return false } diff --git a/Sources/Screens/Organization/OrganizationCreate.swift b/Sources/Screens/Organization/OrganizationCreate.swift index 26e11bf..a209236 100644 --- a/Sources/Screens/Organization/OrganizationCreate.swift +++ b/Sources/Screens/Organization/OrganizationCreate.swift @@ -21,7 +21,9 @@ struct OrganizationCreate: View { @State private var errorMessage: String? private let onCompletion: ((VOOrganization.Entity) -> Void)? - init(organizationStore: OrganizationStore, onCompletion: ((VOOrganization.Entity) -> Void)? = nil) { + init( + organizationStore: OrganizationStore, onCompletion: ((VOOrganization.Entity) -> Void)? = nil + ) { self.organizationStore = organizationStore self.onCompletion = onCompletion } diff --git a/Sources/Screens/Organization/OrganizationEditName.swift b/Sources/Screens/Organization/OrganizationEditName.swift index f31d95e..12ba1ed 100644 --- a/Sources/Screens/Organization/OrganizationEditName.swift +++ b/Sources/Screens/Organization/OrganizationEditName.swift @@ -21,7 +21,9 @@ struct OrganizationEditName: View { @State private var errorMessage: String? private let onCompletion: ((VOOrganization.Entity) -> Void)? - init(organizationStore: OrganizationStore, onCompletion: ((VOOrganization.Entity) -> Void)? = nil) { + init( + organizationStore: OrganizationStore, onCompletion: ((VOOrganization.Entity) -> Void)? = nil + ) { self.organizationStore = organizationStore self.onCompletion = onCompletion } @@ -70,7 +72,8 @@ struct OrganizationEditName: View { var updatedOrganization: VOOrganization.Entity? withErrorHandling { - updatedOrganization = try await organizationStore.patchName(current.id, name: nornalizedValue) + updatedOrganization = try await organizationStore.patchName( + current.id, name: nornalizedValue) return true } success: { dismiss() diff --git a/Sources/Screens/Organization/OrganizationList.swift b/Sources/Screens/Organization/OrganizationList.swift index afe377d..2294f99 100644 --- a/Sources/Screens/Organization/OrganizationList.swift +++ b/Sources/Screens/Organization/OrganizationList.swift @@ -31,7 +31,8 @@ struct OrganizationList: View { List { ForEach(entities, id: \.id) { organization in NavigationLink { - OrganizationOverview(organization, organizationStore: organizationStore) + OrganizationOverview( + organization, organizationStore: organizationStore) } label: { OrganizationRow(organization) .onAppear { diff --git a/Sources/Screens/Organization/OrganizationRow.swift b/Sources/Screens/Organization/OrganizationRow.swift index db38a1e..ae3d328 100644 --- a/Sources/Screens/Organization/OrganizationRow.swift +++ b/Sources/Screens/Organization/OrganizationRow.swift @@ -31,10 +31,11 @@ struct OrganizationRow: View { } #Preview { - OrganizationRow(.init( - id: UUID().uuidString, - name: "My Organization", - permission: .owner, - createTime: Date().ISO8601Format() - )) + OrganizationRow( + .init( + id: UUID().uuidString, + name: "My Organization", + permission: .owner, + createTime: Date().ISO8601Format() + )) } diff --git a/Sources/Screens/Organization/OrganizationSettings.swift b/Sources/Screens/Organization/OrganizationSettings.swift index b5ae094..9c12348 100644 --- a/Sources/Screens/Organization/OrganizationSettings.swift +++ b/Sources/Screens/Organization/OrganizationSettings.swift @@ -33,7 +33,8 @@ struct OrganizationSettings: View { Form { Section(header: VOSectionHeader("Basics")) { NavigationLink { - OrganizationEditName(organizationStore: organizationStore) { updatedOranization in + OrganizationEditName(organizationStore: organizationStore) { + updatedOranization in organizationStore.current = updatedOranization if let index = organizationStore.entities?.firstIndex(where: { $0.id == updatedOranization.id @@ -60,7 +61,9 @@ struct OrganizationSettings: View { VOFormButtonLabel("Delete Organization", isLoading: isDeleting) } .disabled(isDeleting) - .confirmationDialog("Delete Organization", isPresented: $showDeleteConfirmation) { + .confirmationDialog( + "Delete Organization", isPresented: $showDeleteConfirmation + ) { Button("Delete Permanently", role: .destructive) { performDelete() } diff --git a/Sources/Screens/Organization/OrganizationStore.swift b/Sources/Screens/Organization/OrganizationStore.swift index bf593ed..0e8622c 100644 --- a/Sources/Screens/Organization/OrganizationStore.swift +++ b/Sources/Screens/Organization/OrganizationStore.swift @@ -58,7 +58,9 @@ class OrganizationStore: ObservableObject { try await organizationClient?.fetchProbe(.init(query: query, size: size)) } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOOrganization.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOOrganization.List? + { try await organizationClient?.fetchList(.init(query: query, page: page, size: size)) } @@ -158,7 +160,8 @@ class OrganizationStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Server/ServerCreate.swift b/Sources/Screens/Server/ServerCreate.swift index 169d1b0..b166c18 100644 --- a/Sources/Screens/Server/ServerCreate.swift +++ b/Sources/Screens/Server/ServerCreate.swift @@ -60,14 +60,15 @@ struct ServerCreate: View { private func performSave() { isSaving = true Task { - context.insert(Server( - id: UUID().uuidString, - name: normalizedName, - apiURL: apiURL, - idpURL: idpURL, - isCloud: false, - isActive: false - )) + context.insert( + Server( + id: UUID().uuidString, + name: normalizedName, + apiURL: apiURL, + idpURL: idpURL, + isCloud: false, + isActive: false + )) try? context.save() DispatchQueue.main.async { dismiss() diff --git a/Sources/Screens/Server/ServerOverview.swift b/Sources/Screens/Server/ServerOverview.swift index c9cdaf3..f909675 100644 --- a/Sources/Screens/Server/ServerOverview.swift +++ b/Sources/Screens/Server/ServerOverview.swift @@ -121,12 +121,13 @@ struct ServerOverview: View { } #Preview { - ServerOverview(Server( - id: UUID().uuidString, - name: "Local", - apiURL: "http://localhost:8080", - idpURL: "http://localhost:8081", - isCloud: false, - isActive: true - )) + ServerOverview( + Server( + id: UUID().uuidString, + name: "Local", + apiURL: "http://localhost:8080", + idpURL: "http://localhost:8081", + isCloud: false, + isActive: true + )) } diff --git a/Sources/Screens/Sharing/SharingGroupPermission.swift b/Sources/Screens/Sharing/SharingGroupPermission.swift index 9b03023..33f3f9f 100644 --- a/Sources/Screens/Sharing/SharingGroupPermission.swift +++ b/Sources/Screens/Sharing/SharingGroupPermission.swift @@ -90,7 +90,9 @@ struct SharingGroupPermission: View { } } .disabled(isRevoking) - .confirmationDialog("Revoke Permission", isPresented: $showRevoke, titleVisibility: .visible) { + .confirmationDialog( + "Revoke Permission", isPresented: $showRevoke, titleVisibility: .visible + ) { Button("Revoke", role: .destructive) { performRevoke() } @@ -140,7 +142,8 @@ struct SharingGroupPermission: View { guard let group, let permission else { return } isGranting = true withErrorHandling { - try await sharingStore.grantGroupPermission(ids: fileIDs, groupID: group.id, permission: permission) + try await sharingStore.grantGroupPermission( + ids: fileIDs, groupID: group.id, permission: permission) return true } success: { dismiss() diff --git a/Sources/Screens/Sharing/SharingGroupRow.swift b/Sources/Screens/Sharing/SharingGroupRow.swift index e1c7663..10071b7 100644 --- a/Sources/Screens/Sharing/SharingGroupRow.swift +++ b/Sources/Screens/Sharing/SharingGroupRow.swift @@ -40,20 +40,21 @@ struct SharingGroupRow: View { } #Preview { - SharingGroupRow(.init( - id: UUID().uuidString, - group: .init( + SharingGroupRow( + .init( id: UUID().uuidString, - name: "My Group", - organization: .init( + group: .init( id: UUID().uuidString, - name: "My Organization", + name: "My Group", + organization: .init( + id: UUID().uuidString, + name: "My Organization", + permission: .owner, + createTime: Date().ISO8601Format() + ), permission: .owner, createTime: Date().ISO8601Format() ), - permission: .owner, - createTime: Date().ISO8601Format() - ), - permission: .owner - )) + permission: .owner + )) } diff --git a/Sources/Screens/Sharing/SharingStore.swift b/Sources/Screens/Sharing/SharingStore.swift index 850f39e..008310e 100644 --- a/Sources/Screens/Sharing/SharingStore.swift +++ b/Sources/Screens/Sharing/SharingStore.swift @@ -82,16 +82,22 @@ class SharingStore: ObservableObject { // MARK: - Update - func grantUserPermission(ids: [String], userID: String, permission: VOPermission.Value) async throws { - try await fileClient?.grantUserPermission(.init(ids: ids, userID: userID, permission: permission)) + func grantUserPermission(ids: [String], userID: String, permission: VOPermission.Value) + async throws + { + try await fileClient?.grantUserPermission( + .init(ids: ids, userID: userID, permission: permission)) } func revokeUserPermission(id: String, userID: String) async throws { try await fileClient?.revokeUserPermission(.init(ids: [id], userID: userID)) } - func grantGroupPermission(ids: [String], groupID: String, permission: VOPermission.Value) async throws { - try await fileClient?.grantGroupPermission(.init(ids: ids, groupID: groupID, permission: permission)) + func grantGroupPermission(ids: [String], groupID: String, permission: VOPermission.Value) + async throws + { + try await fileClient?.grantGroupPermission( + .init(ids: ids, groupID: groupID, permission: permission)) } func revokeGroupPermission(id: String, groupID: String) async throws { diff --git a/Sources/Screens/Sharing/SharingUserPermission.swift b/Sources/Screens/Sharing/SharingUserPermission.swift index c05a9b2..fda7550 100644 --- a/Sources/Screens/Sharing/SharingUserPermission.swift +++ b/Sources/Screens/Sharing/SharingUserPermission.swift @@ -93,7 +93,9 @@ struct SharingUserPermission: View { } } .disabled(isRevoking) - .confirmationDialog("Revoke Permission", isPresented: $showRevoke, titleVisibility: .visible) { + .confirmationDialog( + "Revoke Permission", isPresented: $showRevoke, titleVisibility: .visible + ) { Button("Revoke", role: .destructive) { performRevoke() } @@ -143,7 +145,8 @@ struct SharingUserPermission: View { guard let user, let permission else { return } isGranting = true withErrorHandling { - try await sharingStore.grantUserPermission(ids: fileIDs, userID: user.id, permission: permission) + try await sharingStore.grantUserPermission( + ids: fileIDs, userID: user.id, permission: permission) return true } success: { dismiss() diff --git a/Sources/Screens/Sharing/SharingUserRow.swift b/Sources/Screens/Sharing/SharingUserRow.swift index ce792dc..87ad8f1 100644 --- a/Sources/Screens/Sharing/SharingUserRow.swift +++ b/Sources/Screens/Sharing/SharingUserRow.swift @@ -46,15 +46,16 @@ struct SharingUserRow: View { } #Preview { - SharingUserRow(.init( - id: UUID().uuidString, - user: VOUser.Entity( + SharingUserRow( + .init( id: UUID().uuidString, - username: "brucelee@example.com", - email: "brucelee@example.com", - fullName: "Bruce Lee", - createTime: Date().ISO8601Format() - ), - permission: .editor - )) + user: VOUser.Entity( + id: UUID().uuidString, + username: "brucelee@example.com", + email: "brucelee@example.com", + fullName: "Bruce Lee", + createTime: Date().ISO8601Format() + ), + permission: .editor + )) } diff --git a/Sources/Screens/SignIn/TokenStore.swift b/Sources/Screens/SignIn/TokenStore.swift index 04a278d..8b5f012 100644 --- a/Sources/Screens/SignIn/TokenStore.swift +++ b/Sources/Screens/SignIn/TokenStore.swift @@ -25,20 +25,23 @@ class TokenStore: ObservableObject { } func signIn(username: String, password: String) async throws -> VOToken.Value { - try await client.exchange(.init( - grantType: .password, - username: username, - password: password - )) + try await client.exchange( + .init( + grantType: .password, + username: username, + password: password + )) } func refreshTokenIfNecessary() async throws -> VOToken.Value? { guard token != nil else { return nil } if let token, token.isExpired { - if let newToken = try? await client.exchange(.init( - grantType: .refreshToken, - refreshToken: token.refreshToken - )) { + if let newToken = try? await client.exchange( + .init( + grantType: .refreshToken, + refreshToken: token.refreshToken + )) + { return newToken } } diff --git a/Sources/Screens/SignUp/SignUp.swift b/Sources/Screens/SignUp/SignUp.swift index 03a6b04..9bcec77 100644 --- a/Sources/Screens/SignUp/SignUp.swift +++ b/Sources/Screens/SignUp/SignUp.swift @@ -50,7 +50,8 @@ struct SignUp: View { PasswordHint("\(passwordRequirements.minLowercase) lowercase character.") PasswordHint("\(passwordRequirements.minUppercase) uppercase character.") PasswordHint("\(passwordRequirements.minNumbers) number.") - PasswordHint("\(passwordRequirements.minSymbols) special character(s) (!#$%).") + PasswordHint( + "\(passwordRequirements.minSymbols) special character(s) (!#$%).") } .frame(width: VOMetrics.formWidth) SecureField("Confirm password", text: $confirmPassword) diff --git a/Sources/Screens/Snapshot/SnapshotOverview.swift b/Sources/Screens/Snapshot/SnapshotOverview.swift index 477f11d..be13f0f 100644 --- a/Sources/Screens/Snapshot/SnapshotOverview.swift +++ b/Sources/Screens/Snapshot/SnapshotOverview.swift @@ -79,7 +79,8 @@ struct SnapshotOverview: View { } } .disabled(isProcessing) - .confirmationDialog("Activate Snapshot", isPresented: $showActivateConfirmation) { + .confirmationDialog("Activate Snapshot", isPresented: $showActivateConfirmation) + { Button("Activate") { performActivate() } diff --git a/Sources/Screens/Snapshot/SnapshotStore.swift b/Sources/Screens/Snapshot/SnapshotStore.swift index e8f3d56..94d0101 100644 --- a/Sources/Screens/Snapshot/SnapshotStore.swift +++ b/Sources/Screens/Snapshot/SnapshotStore.swift @@ -42,18 +42,22 @@ class SnapshotStore: ObservableObject { private func fetchProbe(size: Int = Constants.pageSize) async throws -> VOSnapshot.Probe? { guard let fileID else { return nil } - return try await snapshotClient?.fetchProbe(.init(fileID: fileID, size: size, sortOrder: .desc)) + return try await snapshotClient?.fetchProbe( + .init(fileID: fileID, size: size, sortOrder: .desc)) } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOSnapshot.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOSnapshot + .List? + { guard let fileID else { return nil } - return try await snapshotClient?.fetchList(.init( - fileID: fileID, - page: page, - size: size, - sortBy: .version, - sortOrder: .desc - )) + return try await snapshotClient?.fetchList( + .init( + fileID: fileID, + page: page, + size: size, + sortBy: .version, + sortOrder: .desc + )) } func fetchNextPage(replace: Bool = false) { @@ -147,7 +151,8 @@ class SnapshotStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Task/TaskRow.swift b/Sources/Screens/Task/TaskRow.swift index 032d452..b6caac2 100644 --- a/Sources/Screens/Task/TaskRow.swift +++ b/Sources/Screens/Task/TaskRow.swift @@ -74,55 +74,61 @@ struct TaskRow: View { Form { List { NavigationLink(destination: Color.clear) { - TaskRow(.init( - id: UUID().uuidString, - name: "Measuring image dimensions.", - isIndeterminate: true, - userID: UUID().uuidString, - status: .running, - payload: VOTask.Payload(object: "human-freedom-index-2022.pdf") - )) + TaskRow( + .init( + id: UUID().uuidString, + name: "Measuring image dimensions.", + isIndeterminate: true, + userID: UUID().uuidString, + status: .running, + payload: VOTask.Payload(object: "human-freedom-index-2022.pdf") + )) } NavigationLink(destination: Color.clear) { - TaskRow(.init( - id: UUID().uuidString, - name: "Waiting.", - isIndeterminate: true, - userID: UUID().uuidString, - status: .waiting, - payload: VOTask.Payload(object: "Kubernetes-Patterns-2nd-Edition.pdf") - )) + TaskRow( + .init( + id: UUID().uuidString, + name: "Waiting.", + isIndeterminate: true, + userID: UUID().uuidString, + status: .waiting, + payload: VOTask.Payload(object: "Kubernetes-Patterns-2nd-Edition.pdf") + )) } NavigationLink(destination: Color.clear) { - TaskRow(.init( - id: UUID().uuidString, - name: "Creating thumbnail.", - isIndeterminate: true, - userID: UUID().uuidString, - status: .success, - payload: VOTask.Payload(object: "In_the_Conservatory.tiff") - )) + TaskRow( + .init( + id: UUID().uuidString, + name: "Creating thumbnail.", + isIndeterminate: true, + userID: UUID().uuidString, + status: .success, + payload: VOTask.Payload(object: "In_the_Conservatory.tiff") + )) } NavigationLink(destination: Color.clear) { - TaskRow(.init( - id: UUID().uuidString, - name: "Deleting.", - error: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", - isIndeterminate: true, - userID: UUID().uuidString, - status: .error, - payload: VOTask.Payload(object: "Choose-an-automation-tool-ebook-Red-Hat-Developer.pdf") - )) + TaskRow( + .init( + id: UUID().uuidString, + name: "Deleting.", + error: "Lorem ipsum dolor sit amet, consectetur adipiscing elit.", + isIndeterminate: true, + userID: UUID().uuidString, + status: .error, + payload: VOTask.Payload( + object: "Choose-an-automation-tool-ebook-Red-Hat-Developer.pdf") + )) } NavigationLink(destination: Color.clear) { - TaskRow(.init( - id: UUID().uuidString, - name: "Lorem ipsum dolor sit amet.", - percentage: 50, - isIndeterminate: false, - userID: UUID().uuidString, - status: .running - )) + TaskRow( + .init( + id: UUID().uuidString, + name: "Lorem ipsum dolor sit amet.", + percentage: 50, + isIndeterminate: false, + userID: UUID().uuidString, + status: .running + )) } } } diff --git a/Sources/Screens/Task/TaskStore.swift b/Sources/Screens/Task/TaskStore.swift index e1616f6..63a25fe 100644 --- a/Sources/Screens/Task/TaskStore.swift +++ b/Sources/Screens/Task/TaskStore.swift @@ -43,7 +43,9 @@ class TaskStore: ObservableObject { try await taskClient?.fetchProbe(.init(size: size)) } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOTask.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOTask + .List? + { try await taskClient?.fetchList(.init(page: page, size: size)) } @@ -138,7 +140,8 @@ class TaskStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/User/UserRow.swift b/Sources/Screens/User/UserRow.swift index 2006a7a..ea023a6 100644 --- a/Sources/Screens/User/UserRow.swift +++ b/Sources/Screens/User/UserRow.swift @@ -46,11 +46,12 @@ struct UserRow: View { } #Preview { - UserRow(VOUser.Entity( - id: UUID().uuidString, - username: "brucelee@example.com", - email: "brucelee@example.com", - fullName: "Bruce Lee", - createTime: Date().ISO8601Format() - )) + UserRow( + VOUser.Entity( + id: UUID().uuidString, + username: "brucelee@example.com", + email: "brucelee@example.com", + fullName: "Bruce Lee", + createTime: Date().ISO8601Format() + )) } diff --git a/Sources/Screens/User/UserStore.swift b/Sources/Screens/User/UserStore.swift index 8ebf989..61a6997 100644 --- a/Sources/Screens/User/UserStore.swift +++ b/Sources/Screens/User/UserStore.swift @@ -69,36 +69,42 @@ class UserStore: ObservableObject { private func fetchProbe(size: Int = Constants.pageSize) async throws -> VOUser.Probe? { if let organizationID { - return try await userClient?.fetchProbe(.init( - query: query, - organizationID: organizationID, - size: size - )) + return try await userClient?.fetchProbe( + .init( + query: query, + organizationID: organizationID, + size: size + )) } else if let groupID { - return try await userClient?.fetchProbe(.init( - query: query, - groupID: groupID, - size: size - )) + return try await userClient?.fetchProbe( + .init( + query: query, + groupID: groupID, + size: size + )) } return nil } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOUser.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOUser + .List? + { if let organizationID { - return try await userClient?.fetchList(.init( - query: query, - organizationID: organizationID, - page: page, - size: size - )) + return try await userClient?.fetchList( + .init( + query: query, + organizationID: organizationID, + page: page, + size: size + )) } else if let groupID { - return try await userClient?.fetchList(.init( - query: query, - groupID: groupID, - page: page, - size: size - )) + return try await userClient?.fetchList( + .init( + query: query, + groupID: groupID, + page: page, + size: size + )) } return nil } @@ -184,7 +190,8 @@ class UserStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/Sources/Screens/Viewer/3D/Viewer3D.swift b/Sources/Screens/Viewer/3D/Viewer3D.swift index 22bf5b0..51b13b6 100644 --- a/Sources/Screens/Viewer/3D/Viewer3D.swift +++ b/Sources/Screens/Viewer/3D/Viewer3D.swift @@ -25,10 +25,11 @@ struct Viewer3D: View { var body: some View { VStack { if file.type == .file, - let snapshot = file.snapshot, - let download = snapshot.preview, - let fileExtension = download.fileExtension, fileExtension.isGLB(), - let url = viewer3DStore.url { + let snapshot = file.snapshot, + let download = snapshot.preview, + let fileExtension = download.fileExtension, fileExtension.isGLB(), + let url = viewer3DStore.url + { Viewer3DRenderer(file: file, url: url) .edgesIgnoringSafeArea(.horizontal) } diff --git a/Sources/Screens/Viewer/3D/Viewer3DRenderer.swift b/Sources/Screens/Viewer/3D/Viewer3DRenderer.swift index 884f47d..7ff851a 100644 --- a/Sources/Screens/Viewer/3D/Viewer3DRenderer.swift +++ b/Sources/Screens/Viewer/3D/Viewer3DRenderer.swift @@ -38,7 +38,7 @@ struct Viewer3DRenderer: UIViewRepresentable { sceneView.topAnchor.constraint(equalTo: containerView.topAnchor), sceneView.bottomAnchor.constraint(equalTo: containerView.bottomAnchor), sceneView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), - sceneView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor) + sceneView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor), ]) let spinner = UIActivityIndicatorView(style: .large) @@ -47,7 +47,7 @@ struct Viewer3DRenderer: UIViewRepresentable { spinner.translatesAutoresizingMaskIntoConstraints = false NSLayoutConstraint.activate([ spinner.centerXAnchor.constraint(equalTo: containerView.centerXAnchor), - spinner.centerYAnchor.constraint(equalTo: containerView.centerYAnchor) + spinner.centerYAnchor.constraint(equalTo: containerView.centerYAnchor), ]) context.coordinator.spinner = spinner @@ -137,7 +137,8 @@ struct Viewer3DRenderer: UIViewRepresentable { defaultAnimation.animationPlayer.animation.usesSceneTimeBase = false defaultAnimation.animationPlayer.animation.repeatCount = .greatestFiniteMagnitude - sceneView.scene?.rootNode.addAnimationPlayer(defaultAnimation.animationPlayer, forKey: nil) + sceneView.scene?.rootNode.addAnimationPlayer( + defaultAnimation.animationPlayer, forKey: nil) defaultAnimation.animationPlayer.play() } @@ -169,7 +170,8 @@ struct Viewer3DRenderer: UIViewRepresentable { let adjustedExtent = maxExtent * scaleFactor let distance = adjustedExtent * 2.0 - cameraNode.position = SCNVector3(center.x, center.y + extents.y / 2, center.z + distance) + cameraNode.position = SCNVector3( + center.x, center.y + extents.y / 2, center.z + distance) // Update the camera's look-at point on the main thread to ensure synchronization DispatchQueue.main.async { diff --git a/Sources/Screens/Viewer/Audio/ViewerAudio.swift b/Sources/Screens/Viewer/Audio/ViewerAudio.swift index ad6579d..6cc174d 100644 --- a/Sources/Screens/Viewer/Audio/ViewerAudio.swift +++ b/Sources/Screens/Viewer/Audio/ViewerAudio.swift @@ -23,10 +23,11 @@ struct ViewerAudio: View { var body: some View { VStack { if file.type == .file, - let snapshot = file.snapshot, - let download = snapshot.preview, - let fileExtension = download.fileExtension, fileExtension.isAudio(), - let url = viewerAudioStore.url { + let snapshot = file.snapshot, + let download = snapshot.preview, + let fileExtension = download.fileExtension, fileExtension.isAudio(), + let url = viewerAudioStore.url + { ViewerAudioWebView(url: url) .edgesIgnoringSafeArea(.horizontal) } diff --git a/Sources/Screens/Viewer/Image/ViewerImage.swift b/Sources/Screens/Viewer/Image/ViewerImage.swift index 2535ca7..b5e5b14 100644 --- a/Sources/Screens/Viewer/Image/ViewerImage.swift +++ b/Sources/Screens/Viewer/Image/ViewerImage.swift @@ -23,10 +23,11 @@ struct ViewerImage: View { var body: some View { VStack { if file.type == .file, - let snapshot = file.snapshot, snapshot.mosaic == nil, - let download = snapshot.preview, - let fileExtension = download.fileExtension, fileExtension.isImage(), - let url = viewerImageStore.url { + let snapshot = file.snapshot, snapshot.mosaic == nil, + let download = snapshot.preview, + let fileExtension = download.fileExtension, fileExtension.isImage(), + let url = viewerImageStore.url + { ViewerImageWebView(url: url) .edgesIgnoringSafeArea(.horizontal) } diff --git a/Sources/Screens/Viewer/Mosaic/ViewerMosaic.swift b/Sources/Screens/Viewer/Mosaic/ViewerMosaic.swift index 385e3cd..4c80047 100644 --- a/Sources/Screens/Viewer/Mosaic/ViewerMosaic.swift +++ b/Sources/Screens/Viewer/Mosaic/ViewerMosaic.swift @@ -26,21 +26,25 @@ struct ViewerMosaic: View { var body: some View { if file.type == .file, - let snapshot = file.snapshot, - let download = snapshot.preview, - let fileExtension = download.fileExtension, fileExtension.isImage(), snapshot.mosaic != nil { + let snapshot = file.snapshot, + let download = snapshot.preview, + let fileExtension = download.fileExtension, fileExtension.isImage(), + snapshot.mosaic != nil + { GeometryReader { geometry in let visibleRect = CGRect( origin: CGPoint(x: -dragOffset.width, y: -dragOffset.height), size: geometry.size ) ZStack { - if let zoomLevel = viewerMosaicStore.zoomLevel, !viewerMosaicStore.grid.isEmpty { - ForEach(0 ..< zoomLevel.rows, id: \.self) { row in - ForEach(0 ..< zoomLevel.cols, id: \.self) { col in + if let zoomLevel = viewerMosaicStore.zoomLevel, !viewerMosaicStore.grid.isEmpty + { + ForEach(0.. Bool { - !normalizedName.isEmpty && - organization != nil && - storageCapacity != nil && - storageCapacity! > 0 + !normalizedName.isEmpty && organization != nil && storageCapacity != nil + && storageCapacity! > 0 } } diff --git a/Sources/Screens/Workspace/WorkspaceEditName.swift b/Sources/Screens/Workspace/WorkspaceEditName.swift index 2bb8aa1..8452454 100644 --- a/Sources/Screens/Workspace/WorkspaceEditName.swift +++ b/Sources/Screens/Workspace/WorkspaceEditName.swift @@ -88,8 +88,9 @@ struct WorkspaceEditName: View { private func isValid() -> Bool { if let current = workspaceStore.current, - !normalizedValue.isEmpty, - normalizedValue != current.name { + !normalizedValue.isEmpty, + normalizedValue != current.name + { return true } return false diff --git a/Sources/Screens/Workspace/WorkspaceList.swift b/Sources/Screens/Workspace/WorkspaceList.swift index 2f657c7..970f884 100644 --- a/Sources/Screens/Workspace/WorkspaceList.swift +++ b/Sources/Screens/Workspace/WorkspaceList.swift @@ -120,15 +120,13 @@ struct WorkspaceList: View { } private var isLoading: Bool { - workspaceStore.entities == nil || - accountStore.identityUserIsLoading || - invitationStore.incomingCountIsLoading + workspaceStore.entities == nil || accountStore.identityUserIsLoading + || invitationStore.incomingCountIsLoading } private var error: String? { - workspaceStore.entitiesError ?? - accountStore.identityUserError ?? - invitationStore.incomingCountError + workspaceStore.entitiesError ?? accountStore.identityUserError + ?? invitationStore.incomingCountError } private var accountButton: some View { diff --git a/Sources/Screens/Workspace/WorkspaceRow.swift b/Sources/Screens/Workspace/WorkspaceRow.swift index e573545..5b0cfe5 100644 --- a/Sources/Screens/Workspace/WorkspaceRow.swift +++ b/Sources/Screens/Workspace/WorkspaceRow.swift @@ -38,18 +38,19 @@ struct WorkspaceRow: View { } #Preview { - WorkspaceRow(.init( - id: UUID().uuidString, - name: "My Workspace", - permission: .owner, - storageCapacity: 100_000_000, - rootID: UUID().uuidString, - organization: .init( + WorkspaceRow( + .init( id: UUID().uuidString, - name: "My Organization", + name: "My Workspace", permission: .owner, + storageCapacity: 100_000_000, + rootID: UUID().uuidString, + organization: .init( + id: UUID().uuidString, + name: "My Organization", + permission: .owner, + createTime: Date().description + ), createTime: Date().description - ), - createTime: Date().description - )) + )) } diff --git a/Sources/Screens/Workspace/WorkspaceSettings.swift b/Sources/Screens/Workspace/WorkspaceSettings.swift index 95ea901..7f33dc4 100644 --- a/Sources/Screens/Workspace/WorkspaceSettings.swift +++ b/Sources/Screens/Workspace/WorkspaceSettings.swift @@ -35,14 +35,19 @@ struct WorkspaceSettings: View { VStack(alignment: .leading) { if let storageUsage = workspaceStore.storageUsage { // swiftlint:disable:next line_length - Text("\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used") + Text( + "\(storageUsage.bytes.prettyBytes()) of \(storageUsage.maxBytes.prettyBytes()) used" + ) ProgressView(value: Double(storageUsage.percentage) / 100.0) } else { Text("Calculating…") ProgressView() } } - NavigationLink(destination: WorkspaceEditStorageCapacity(workspaceStore: workspaceStore)) { + NavigationLink( + destination: WorkspaceEditStorageCapacity( + workspaceStore: workspaceStore) + ) { HStack { Text("Capacity") Spacer() @@ -81,7 +86,9 @@ struct WorkspaceSettings: View { VOFormButtonLabel("Delete Workspace", isLoading: isDeleting) } .disabled(isDeleting) - .confirmationDialog("Delete Workspace", isPresented: $showDeleteConfirmation) { + .confirmationDialog( + "Delete Workspace", isPresented: $showDeleteConfirmation + ) { Button("Delete Permanently", role: .destructive) { performDelete() } diff --git a/Sources/Screens/Workspace/WorkspaceStore.swift b/Sources/Screens/Workspace/WorkspaceStore.swift index f00c1bf..5fe8fda 100644 --- a/Sources/Screens/Workspace/WorkspaceStore.swift +++ b/Sources/Screens/Workspace/WorkspaceStore.swift @@ -72,7 +72,9 @@ class WorkspaceStore: ObservableObject { try await workspaceClient?.fetchProbe(.init(query: query, size: size)) } - private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws -> VOWorkspace.List? { + private func fetchList(page: Int = 1, size: Int = Constants.pageSize) async throws + -> VOWorkspace.List? + { try await workspaceClient?.fetchList(.init(query: query, page: page, size: size)) } @@ -168,11 +170,12 @@ class WorkspaceStore: ObservableObject { organization: VOOrganization.Entity, storageCapacity: Int ) async throws -> VOWorkspace.Entity? { - try await workspaceClient?.create(.init( - name: name, - organizationID: organization.id, - storageCapacity: storageCapacity - )) + try await workspaceClient?.create( + .init( + name: name, + organizationID: organization.id, + storageCapacity: storageCapacity + )) } func patchName(_ id: String, name: String) async throws -> VOWorkspace.Entity? { @@ -230,7 +233,8 @@ class WorkspaceStore: ObservableObject { if let entities { let threashold = Constants.pageSize / 2 if entities.count >= threashold, - entities.firstIndex(where: { $0.id == id }) == entities.count - threashold { + entities.firstIndex(where: { $0.id == id }) == entities.count - threashold + { return true } else { return id == entities.last?.id diff --git a/ci/swiftformat.zip b/ci/swiftformat.zip deleted file mode 100644 index fefb376..0000000 Binary files a/ci/swiftformat.zip and /dev/null differ