From 6c307aba6305db3865a0beb09d62d4d7e1f96bdf Mon Sep 17 00:00:00 2001 From: Thomas Ricouard Date: Mon, 13 Mar 2023 13:38:28 +0100 Subject: [PATCH] SwiftFormat --- IceCubesApp/App/AppRouter.swift | 2 +- IceCubesApp/App/IceCubesApp.swift | 11 ++-- IceCubesApp/App/Tabs/Settings/AboutView.swift | 6 +- .../Tabs/Settings/AccountSettingView.swift | 2 +- .../App/Tabs/Settings/AddAccountsView.swift | 26 ++++---- .../Tabs/Settings/ContentSettingsView.swift | 4 +- .../Tabs/Settings/DisplaySettingsView.swift | 36 +++++------ .../App/Tabs/Settings/SupportAppView.swift | 29 +++++---- IceCubesApp/App/Tabs/Tabs.swift | 2 +- .../ShareViewController.swift | 3 +- .../Account/AccountDetailContextMenu.swift | 6 +- .../Sources/Account/AccountDetailView.swift | 13 ++-- .../Account/AccountDetailViewModel.swift | 6 +- .../AccountsList/AccountsListRow.swift | 7 +-- .../Account/Filters/EditFilterView.swift | 25 ++++---- .../Sources/AppAccount/AppAccountView.swift | 5 +- .../AppAccount/AppAccountsSelectorView.swift | 12 ++-- .../Detail/ConversationMessageView.swift | 3 +- .../List/ConversationsListView.swift | 3 +- .../Sources/DesignSystem/Font.swift | 12 ++-- .../Sources/DesignSystem/SFSymbols.swift | 9 +-- .../Env/Sources/Env/CustomEnvValues.swift | 2 +- Packages/Env/Sources/Env/Duration.swift | 4 +- Packages/Env/Sources/Env/Router.swift | 1 - .../Env/Sources/Env/SoundEffectManager.swift | 4 +- .../Sources/Env/StatusDataController.swift | 61 +++++++++---------- .../Env/Sources/Env/StatusEmbedCache.swift | 2 +- .../Env/Sources/Env/UserPreferences.swift | 4 +- .../Explore/Sources/Explore/ExploreView.swift | 44 +++++++------ .../Sources/Explore/TagsListView.swift | 10 +-- .../Models/Sources/Models/ServerError.swift | 1 + .../Models/Sources/Models/ServerFilter.swift | 6 +- Packages/Models/Sources/Models/Status.swift | 3 - Packages/Network/Sources/Network/Client.swift | 11 ++-- .../Sources/Network/Endpoint/Oauth.swift | 4 +- .../Sources/Network/OpenAIClient.swift | 14 ++--- .../Notifications/NotificationTypeExt.swift | 14 ++--- .../Notifications/NotificationsListView.swift | 3 +- .../Status/Detail/StatusDetailView.swift | 3 +- .../Status/Detail/StatusDetailViewModel.swift | 6 +- .../StatusEditorAccessoryView.swift | 4 +- .../Components/StatusEditorCompressor.swift | 42 ++++++------- .../StatusEditorUTTypeSupported.swift | 4 +- .../Status/Editor/StatusEditorView.swift | 2 +- .../Status/Editor/StatusEditorViewModel.swift | 15 +++-- .../Status/List/StatusesListView.swift | 38 ++++++------ .../Status/Media/VideoPlayerView.swift | 3 +- .../Sources/Status/Row/StatusRowView.swift | 22 +++---- .../Status/Row/StatusRowViewModel.swift | 26 ++++---- .../Row/Subviews/StatusRowActionsView.swift | 9 +-- .../Row/Subviews/StatusRowContextMenu.swift | 3 +- .../Row/Subviews/StatusRowDetailView.swift | 2 +- .../Subviews/StatusRowMediaPreviewView.swift | 3 +- .../Row/Subviews/StatusRowSwipeView.swift | 12 ++-- .../Row/Subviews/StatusRowTextView.swift | 2 +- .../Sources/Timeline/TimelineCache.swift | 2 +- .../Sources/Timeline/TimelineDatasource.swift | 2 +- .../Sources/Timeline/TimelineViewModel.swift | 2 +- 58 files changed, 313 insertions(+), 299 deletions(-) diff --git a/IceCubesApp/App/AppRouter.swift b/IceCubesApp/App/AppRouter.swift index 3612ca9e..addc10f5 100644 --- a/IceCubesApp/App/AppRouter.swift +++ b/IceCubesApp/App/AppRouter.swift @@ -3,13 +3,13 @@ import AppAccount import Conversations import DesignSystem import Env +import Explore import LinkPresentation import Lists import Models import Status import SwiftUI import Timeline -import Explore @MainActor extension View { diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index e7389dac..56a54d61 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -112,7 +112,8 @@ struct IceCubesApp: App { SideBarView(selectedTab: $selectedTab, popToRootTab: $popToRootTab, tabs: availableTabs, - routerPath: sidebarRouterPath) { + routerPath: sidebarRouterPath) + { GeometryReader { _ in HStack(spacing: 0) { ZStack { @@ -165,12 +166,12 @@ struct IceCubesApp: App { popToRootTab = selectedTab } } - + HapticManager.shared.fireHaptic(of: .tabSelection) SoundEffectManager.shared.playSound(of: .tabSelection) - + selectedTab = newTab - + DispatchQueue.main.async { if selectedTab == .notifications, let token = appAccountsManager.currentAccount.oauthToken @@ -179,7 +180,7 @@ struct IceCubesApp: App { watcher.unreadNotificationsCount = 0 } } - + })) { ForEach(availableTabs) { tab in tab.makeContentView(popToRootTab: $popToRootTab) diff --git a/IceCubesApp/App/Tabs/Settings/AboutView.swift b/IceCubesApp/App/Tabs/Settings/AboutView.swift index 9acd0361..3b43640d 100644 --- a/IceCubesApp/App/Tabs/Settings/AboutView.swift +++ b/IceCubesApp/App/Tabs/Settings/AboutView.swift @@ -39,11 +39,11 @@ struct AboutView: View { .cornerRadius(4) Spacer() } - + Link(destination: URL(string: "https://github.com/Dimillian/IceCubesApp/blob/main/PRIVACY.MD")!) { Label("settings.support.privacy-policy", systemImage: "lock") } - + Link(destination: URL(string: "https://github.com/Dimillian/IceCubesApp/blob/main/TERMS.MD")!) { Label("settings.support.terms-of-use", systemImage: "checkmark.shield") } @@ -51,7 +51,7 @@ struct AboutView: View { Text("\(versionNumber)©2023 Thomas Ricouard") } .listRowBackground(theme.primaryBackgroundColor) - + Section { Text(""" • [EmojiText](https://github.com/divadretlaw/EmojiText) diff --git a/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift b/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift index d1df606f..84ec34f4 100644 --- a/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift +++ b/IceCubesApp/App/Tabs/Settings/AccountSettingView.swift @@ -74,7 +74,7 @@ struct AccountSettingsView: View { } } .listRowBackground(theme.primaryBackgroundColor) - + Section { Button(role: .destructive) { if let token = appAccount.oauthToken { diff --git a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift index b1bd5009..dace26a1 100644 --- a/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift +++ b/IceCubesApp/App/Tabs/Settings/AddAccountsView.swift @@ -28,19 +28,17 @@ struct AddAccountView: View { @State private var oauthURL: URL? private let instanceNamePublisher = PassthroughSubject() - + private var sanitizedName: String { - get { - var name = instanceName - .replacingOccurrences(of: "http://", with: "") - .replacingOccurrences(of: "https://", with: "") - - if name.contains("@") { - let parts = name.components(separatedBy: "@") - name = parts[parts.count-1] // [@]username@server.address.com - } - return name + var name = instanceName + .replacingOccurrences(of: "http://", with: "") + .replacingOccurrences(of: "https://", with: "") + + if name.contains("@") { + let parts = name.components(separatedBy: "@") + name = parts[parts.count - 1] // [@]username@server.address.com } + return name } @FocusState private var isInstanceURLFieldFocused: Bool @@ -94,8 +92,8 @@ struct AddAccountView: View { .onChange(of: instanceName) { newValue in instanceNamePublisher.send(newValue) } - .onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { newValue in - //let newValue = newValue + .onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { _ in + // let newValue = newValue // .replacingOccurrences(of: "http://", with: "") // .replacingOccurrences(of: "https://", with: "") let client = Client(server: sanitizedName) @@ -106,7 +104,7 @@ struct AddAccountView: View { let instance: Instance = try await client.get(endpoint: Instances.instance) withAnimation { self.instance = instance - self.instanceName = sanitizedName // clean up the text box, principally to chop off the username if present so it's clear that you might not wind up siging in as the thing in the box + self.instanceName = sanitizedName // clean up the text box, principally to chop off the username if present so it's clear that you might not wind up siging in as the thing in the box } instanceFetchError = nil } else { diff --git a/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift b/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift index eadb43ae..79b14a93 100644 --- a/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift @@ -48,14 +48,14 @@ struct ContentSettingsView: View { Text("settings.content.expand-spoilers") } .disabled(userPreferences.useInstanceContentSettings) - + Picker("settings.content.expand-media", selection: $userPreferences.appAutoExpandMedia) { ForEach(ServerPreferences.AutoExpandMedia.allCases, id: \.rawValue) { media in Text(media.description).tag(media) } } .disabled(userPreferences.useInstanceContentSettings) - + Toggle(isOn: $userPreferences.collapseLongPosts) { Text("settings.content.collapse-long-posts") } diff --git a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift index 80c81dd2..eb50a629 100644 --- a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift @@ -1,35 +1,35 @@ +import Combine import DesignSystem import Env import Models import Network import Status import SwiftUI -import Combine class DisplaySettingsLocalColors: ObservableObject { @Published var tintColor = Theme.shared.tintColor @Published var primaryBackgroundColor = Theme.shared.primaryBackgroundColor @Published var secondaryBackgroundColor = Theme.shared.secondaryBackgroundColor @Published var labelColor = Theme.shared.labelColor - + private var subscriptions = Set() - + init() { $tintColor .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main) - .sink(receiveValue: { newColor in Theme.shared.tintColor = newColor } ) + .sink(receiveValue: { newColor in Theme.shared.tintColor = newColor }) .store(in: &subscriptions) $primaryBackgroundColor .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main) - .sink(receiveValue: { newColor in Theme.shared.primaryBackgroundColor = newColor } ) + .sink(receiveValue: { newColor in Theme.shared.primaryBackgroundColor = newColor }) .store(in: &subscriptions) $secondaryBackgroundColor .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main) - .sink(receiveValue: { newColor in Theme.shared.secondaryBackgroundColor = newColor } ) + .sink(receiveValue: { newColor in Theme.shared.secondaryBackgroundColor = newColor }) .store(in: &subscriptions) $labelColor .debounce(for: .seconds(0.5), scheduler: DispatchQueue.main) - .sink(receiveValue: { newColor in Theme.shared.labelColor = newColor } ) + .sink(receiveValue: { newColor in Theme.shared.labelColor = newColor }) .store(in: &subscriptions) } } @@ -40,15 +40,15 @@ struct DisplaySettingsView: View { @Environment(\.colorScheme) private var colorScheme @EnvironmentObject private var theme: Theme @EnvironmentObject private var userPreferences: UserPreferences - + @StateObject private var localColors = DisplaySettingsLocalColors() @State private var isFontSelectorPresented = false - + private let previewStatusViewModel = StatusRowViewModel(status: Status.placeholder(forSettings: true, language: "la"), client: Client(server: ""), routerPath: RouterPath()) // translate from latin button - + var body: some View { Form { exampleSection @@ -62,14 +62,14 @@ struct DisplaySettingsView: View { .scrollContentBackground(.hidden) .background(theme.secondaryBackgroundColor) } - + private var exampleSection: some View { Section("settings.display.example-toot") { StatusRowView(viewModel: { previewStatusViewModel }) .allowsHitTesting(false) } } - + private var themeSection: some View { Section { Toggle("settings.display.theme.systemColor", isOn: $theme.followSystemColorScheme) @@ -97,7 +97,7 @@ struct DisplaySettingsView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private var fontSection: some View { Section("settings.display.section.font") { Picker("settings.display.font", selection: .init(get: { () -> FontState in @@ -140,7 +140,7 @@ struct DisplaySettingsView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private var layoutSection: some View { Section("settings.display.section.display") { Picker("settings.display.avatar.position", selection: $theme.avatarPosition) { @@ -169,7 +169,7 @@ struct DisplaySettingsView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + @ViewBuilder private var platformsSection: some View { if UIDevice.current.userInterfaceIdiom == .phone { @@ -186,7 +186,7 @@ struct DisplaySettingsView: View { .listRowBackground(theme.primaryBackgroundColor) } } - + private var resetSection: some View { Section { Button { @@ -195,12 +195,12 @@ struct DisplaySettingsView: View { theme.avatarShape = .rounded theme.avatarPosition = .top theme.statusActionsDisplay = .full - + localColors.tintColor = theme.tintColor localColors.primaryBackgroundColor = theme.primaryBackgroundColor localColors.secondaryBackgroundColor = theme.secondaryBackgroundColor localColors.labelColor = theme.labelColor - + } label: { Text("settings.display.restore") } diff --git a/IceCubesApp/App/Tabs/Settings/SupportAppView.swift b/IceCubesApp/App/Tabs/Settings/SupportAppView.swift index 1690364a..c5b133b3 100644 --- a/IceCubesApp/App/Tabs/Settings/SupportAppView.swift +++ b/IceCubesApp/App/Tabs/Settings/SupportAppView.swift @@ -48,7 +48,7 @@ struct SupportAppView: View { } @EnvironmentObject private var theme: Theme - + @Environment(\.openURL) private var openURL @State private var loadingProducts: Bool = false @@ -86,7 +86,7 @@ struct SupportAppView: View { refreshUserInfo() } } - + private func purchase(product: StoreProduct) async { if !isProcessingPurchase { isProcessingPurchase = true @@ -101,23 +101,23 @@ struct SupportAppView: View { isProcessingPurchase = false } } - + private func fetchStoreProducts() { Purchases.shared.getProducts(Tip.allCases.map { $0.productId }) { products in self.subscription = products.first(where: { $0.productIdentifier == Tip.supporter.productId }) - self.products = products.filter{ $0.productIdentifier != Tip.supporter.productId}.sorted(by: { $0.price < $1.price }) + self.products = products.filter { $0.productIdentifier != Tip.supporter.productId }.sorted(by: { $0.price < $1.price }) withAnimation { loadingProducts = false } } } - + private func refreshUserInfo() { Purchases.shared.getCustomerInfo { info, _ in self.customerInfo = info } } - + private func makePurchaseButton(product: StoreProduct) -> some View { Button { Task { @@ -133,7 +133,7 @@ struct SupportAppView: View { } .buttonStyle(.bordered) } - + private var aboutSection: some View { Section { HStack(alignment: .top, spacing: 12) { @@ -152,7 +152,7 @@ struct SupportAppView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private var subscriptionSection: some View { Section { if loadingProducts { @@ -163,14 +163,14 @@ struct SupportAppView: View { Text(Image(systemName: "checkmark.seal.fill")) .foregroundColor(theme.tintColor) .baselineOffset(-1) + - Text("settings.support.supporter.subscribed") + Text("settings.support.supporter.subscribed") .font(.scaledSubheadline) } else { VStack(alignment: .leading) { Text(Image(systemName: "checkmark.seal.fill")) .foregroundColor(theme.tintColor) .baselineOffset(-1) + - Text(Tip.supporter.title) + Text(Tip.supporter.title) .font(.scaledSubheadline) Text(Tip.supporter.subtitle) .font(.scaledFootnote) @@ -179,7 +179,6 @@ struct SupportAppView: View { Spacer() makePurchaseButton(product: subscription) } - } .padding(.vertical, 8) } @@ -190,7 +189,7 @@ struct SupportAppView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private var tipsSection: some View { Section { if loadingProducts { @@ -215,7 +214,7 @@ struct SupportAppView: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private var restorePurchase: some View { Section { HStack { @@ -234,7 +233,7 @@ struct SupportAppView: View { } .listRowBackground(theme.secondaryBackgroundColor) } - + private var linksSection: some View { Section { VStack(alignment: .leading, spacing: 16) { @@ -254,7 +253,7 @@ struct SupportAppView: View { } .listRowBackground(theme.secondaryBackgroundColor) } - + private var loadingPlaceholder: some View { HStack { VStack(alignment: .leading) { diff --git a/IceCubesApp/App/Tabs/Tabs.swift b/IceCubesApp/App/Tabs/Tabs.swift index 0b675324..f65e3df3 100644 --- a/IceCubesApp/App/Tabs/Tabs.swift +++ b/IceCubesApp/App/Tabs/Tabs.swift @@ -1,9 +1,9 @@ import Account +import DesignSystem import Explore import Foundation import Status import SwiftUI -import DesignSystem enum Tab: Int, Identifiable, Hashable { case timeline, notifications, mentions, explore, messages, settings, other diff --git a/IceCubesShareExtension/ShareViewController.swift b/IceCubesShareExtension/ShareViewController.swift index a9707fd3..7c5624e5 100644 --- a/IceCubesShareExtension/ShareViewController.swift +++ b/IceCubesShareExtension/ShareViewController.swift @@ -54,7 +54,8 @@ class ShareViewController: UIViewController { NotificationCenter.default.addObserver(forName: NotificationsName.shareSheetClose, object: nil, - queue: nil) { _ in + queue: nil) + { _ in self.close() } } diff --git a/Packages/Account/Sources/Account/AccountDetailContextMenu.swift b/Packages/Account/Sources/Account/AccountDetailContextMenu.swift index 11b79355..7f5f0a12 100644 --- a/Packages/Account/Sources/Account/AccountDetailContextMenu.swift +++ b/Packages/Account/Sources/Account/AccountDetailContextMenu.swift @@ -1,15 +1,15 @@ -import SwiftUI import Env import Network +import SwiftUI public struct AccountDetailContextMenu: View { @EnvironmentObject private var client: Client @EnvironmentObject private var routerPath: RouterPath @EnvironmentObject private var currentInstance: CurrentInstance @EnvironmentObject private var preferences: UserPreferences - + @ObservedObject var viewModel: AccountDetailViewModel - + public var body: some View { if let account = viewModel.account { Section(account.acct) { diff --git a/Packages/Account/Sources/Account/AccountDetailView.swift b/Packages/Account/Sources/Account/AccountDetailView.swift index 00a33d3f..abf5c40b 100644 --- a/Packages/Account/Sources/Account/AccountDetailView.swift +++ b/Packages/Account/Sources/Account/AccountDetailView.swift @@ -51,7 +51,8 @@ public struct AccountDetailView: View { Picker("", selection: $viewModel.selectedTab) { ForEach(isCurrentUser ? AccountDetailViewModel.Tab.currentAccountTabs : AccountDetailViewModel.Tab.accountTabs, - id: \.self) { tab in + id: \.self) + { tab in Image(systemName: tab.iconName) .tag(tab) } @@ -300,7 +301,7 @@ public struct AccountDetailView: View { ToolbarItem(placement: .navigationBarTrailing) { Menu { AccountDetailContextMenu(viewModel: viewModel) - + if !viewModel.isCurrentUser { Button { isEditingRelationshipNote = true @@ -308,7 +309,7 @@ public struct AccountDetailView: View { Label("account.relation.note.edit", systemImage: "pencil") } } - + if isCurrentUser { Button { isEditingAccount = true @@ -329,10 +330,10 @@ public struct AccountDetailView: View { } label: { Label("settings.push.navigation-title", systemImage: "bell") } - + if let account = viewModel.account { Divider() - + Button { if let url = URL(string: "https://mastometrics.com/auth/login?username=\(account.acct)@\(client.server)&instance=\(client.server)&auto=true") { openURL(url) @@ -343,7 +344,7 @@ public struct AccountDetailView: View { Divider() } - + Button { routerPath.presentedSheet = .settings } label: { diff --git a/Packages/Account/Sources/Account/AccountDetailViewModel.swift b/Packages/Account/Sources/Account/AccountDetailViewModel.swift index 90d248aa..3786711f 100644 --- a/Packages/Account/Sources/Account/AccountDetailViewModel.swift +++ b/Packages/Account/Sources/Account/AccountDetailViewModel.swift @@ -137,9 +137,9 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher { featuredTags: featuredTags, relationships: relationships) } catch { - return try await .init(account: account, - featuredTags: [], - relationships: relationships) + return try await .init(account: account, + featuredTags: [], + relationships: relationships) } } return try await .init(account: account, diff --git a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift index c997a177..d1ba6fdc 100644 --- a/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift +++ b/Packages/Account/Sources/Account/AccountsList/AccountsListRow.swift @@ -26,9 +26,9 @@ public struct AccountsListRow: View { @EnvironmentObject private var client: Client @StateObject var viewModel: AccountsListRowViewModel - + @State private var isEditingRelationshipNote: Bool = false - + let isFollowRequest: Bool let requestUpdated: (() -> Void)? @@ -89,7 +89,7 @@ public struct AccountsListRow: View { AccountDetailHeaderView(viewModel: .init(account: viewModel.account), account: viewModel.account, scrollViewProxy: nil) - .applyAccountDetailsRowStyle(theme: theme) + .applyAccountDetailsRowStyle(theme: theme) } .listStyle(.plain) .scrollContentBackground(.hidden) @@ -98,6 +98,5 @@ public struct AccountsListRow: View { .environmentObject(currentAccount) .environmentObject(client) } - } } diff --git a/Packages/Account/Sources/Account/Filters/EditFilterView.swift b/Packages/Account/Sources/Account/Filters/EditFilterView.swift index 8550e041..321dadf5 100644 --- a/Packages/Account/Sources/Account/Filters/EditFilterView.swift +++ b/Packages/Account/Sources/Account/Filters/EditFilterView.swift @@ -23,9 +23,9 @@ struct EditFilterView: View { @FocusState private var isTitleFocused: Bool private var data: ServerFilterData { - var expiresIn: String? = nil; + var expiresIn: String? // we add 50 seconds, otherwise we immediately show 6d for a 7d filter (6d, 23h, 59s) - switch(expirySelection){ + switch expirySelection { case .infinite: expiresIn = "" // need to send an empty value in order for the server to clear this field in the filter case .custom: @@ -33,11 +33,11 @@ struct EditFilterView: View { default: expiresIn = String(expirySelection.rawValue + 50) } - + return ServerFilterData(title: title, - context: contexts, - filterAction: filterAction, - expiresIn: expiresIn) + context: contexts, + filterAction: filterAction, + expiresIn: expiresIn) } private var canSave: Bool { @@ -53,7 +53,7 @@ struct EditFilterView: View { _expiresAt = .init(initialValue: filter?.expiresAt?.asDate) _expirySelection = .init(initialValue: filter?.expiresAt == nil ? .infinite : .custom) } - + var body: some View { Form { titleSection @@ -95,15 +95,14 @@ struct EditFilterView: View { } if expirySelection != .infinite { DatePicker("filter.edit.expiry.date-time", - selection: Binding(get: {self.expiresAt ?? Date()}, set: {self.expiresAt = $0}), - displayedComponents: [.date, .hourAndMinute] - ) - .disabled(expirySelection != .custom) + selection: Binding(get: { self.expiresAt ?? Date() }, set: { self.expiresAt = $0 }), + displayedComponents: [.date, .hourAndMinute]) + .disabled(expirySelection != .custom) } } .listRowBackground(theme.primaryBackgroundColor) } - + @ViewBuilder private var titleSection: some View { Section("filter.edit.title") { @@ -116,7 +115,7 @@ struct EditFilterView: View { } } .listRowBackground(theme.primaryBackgroundColor) - + if filter == nil, !title.isEmpty { Section { Button { diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift index f3c47f8e..747ba33e 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountView.swift @@ -7,7 +7,7 @@ public struct AppAccountView: View { @EnvironmentObject private var routerPath: RouterPath @EnvironmentObject private var appAccounts: AppAccountsManager @EnvironmentObject private var preferences: UserPreferences - + @StateObject var viewModel: AppAccountViewModel public init(viewModel: AppAccountViewModel) { @@ -51,7 +51,8 @@ public struct AppAccountView: View { .offset(x: 5, y: -5) } else if viewModel.showBadge, let token = viewModel.appAccount.oauthToken, - preferences.getNotificationsCount(for: token) > 0 { + preferences.getNotificationsCount(for: token) > 0 + { let notificationsCount = preferences.getNotificationsCount(for: token) ZStack { Circle() diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index e65c3fb7..325be2b1 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -23,7 +23,7 @@ public struct AppAccountsSelectorView: View { .map { preferences.getNotificationsCount(for: $0) } .reduce(0, +) > 0 } - + private var preferredHeight: CGFloat { var baseHeight: CGFloat = 220 baseHeight += CGFloat(60 * accountsViewModel.count) @@ -48,9 +48,9 @@ public struct AppAccountsSelectorView: View { } .sheet(isPresented: $isPresented, content: { accountsView.presentationDetents([.height(preferredHeight), .large]) - .onAppear { - refreshAccounts() - } + .onAppear { + refreshAccounts() + } }) .onChange(of: currentAccount.account?.id) { _ in refreshAccounts() @@ -88,7 +88,7 @@ public struct AppAccountsSelectorView: View { } } .listRowBackground(theme.primaryBackgroundColor) - + if accountCreationEnabled { Section { Button { @@ -121,7 +121,7 @@ public struct AppAccountsSelectorView: View { } } } - + private var settingsButton: some View { Button { isPresented = false diff --git a/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift b/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift index e2090911..bc95ebea 100644 --- a/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift +++ b/Packages/Conversations/Sources/Conversations/Detail/ConversationMessageView.swift @@ -177,7 +177,8 @@ struct ConversationMessageView: View { let width = mediaWidth(proxy: proxy) if let url = attachement.url { LazyImage(request: makeImageRequest(for: url, - size: .init(width: width, height: 200))) { state in + size: .init(width: width, height: 200))) + { state in if let image = state.image { image .resizable() diff --git a/Packages/Conversations/Sources/Conversations/List/ConversationsListView.swift b/Packages/Conversations/Sources/Conversations/List/ConversationsListView.swift index eec80a53..b47c2285 100644 --- a/Packages/Conversations/Sources/Conversations/List/ConversationsListView.swift +++ b/Packages/Conversations/Sources/Conversations/List/ConversationsListView.swift @@ -47,7 +47,8 @@ public struct ConversationsListView: View { } else if viewModel.isError { ErrorView(title: "conversations.error.title", message: "conversations.error.message", - buttonTitle: "conversations.error.button") { + buttonTitle: "conversations.error.button") + { Task { await viewModel.fetchConversations() } diff --git a/Packages/DesignSystem/Sources/DesignSystem/Font.swift b/Packages/DesignSystem/Sources/DesignSystem/Font.swift index 15c16688..31342216 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/Font.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/Font.swift @@ -44,15 +44,15 @@ public extension Font { static var scaledHeadline: Font { customFont(size: userScaledFontSize(baseSize: headline), relativeTo: .headline).weight(.semibold) } - + static var scaledHeadlineFont: UIFont { customUIFont(size: userScaledFontSize(baseSize: headline)) } - + static var scaledBodyFocused: Font { customFont(size: userScaledFontSize(baseSize: body + 2), relativeTo: .body) } - + static var scaledBodyFocusedFont: UIFont { customUIFont(size: userScaledFontSize(baseSize: body + 2)) } @@ -109,11 +109,13 @@ public extension UIFont { } return UIFont(descriptor: descriptor, size: pointSize) } + var emojiSize: CGFloat { - self.pointSize + pointSize } + var emojiBaselineOffset: CGFloat { // Center emoji with capital letter size of font - -(self.emojiSize - self.capHeight) / 2 + -(emojiSize - capHeight) / 2 } } diff --git a/Packages/DesignSystem/Sources/DesignSystem/SFSymbols.swift b/Packages/DesignSystem/Sources/DesignSystem/SFSymbols.swift index 3e3f1050..bce86087 100644 --- a/Packages/DesignSystem/Sources/DesignSystem/SFSymbols.swift +++ b/Packages/DesignSystem/Sources/DesignSystem/SFSymbols.swift @@ -7,15 +7,12 @@ import SwiftUI // images named in lower case are Apple's symbols // images inamed in CamelCase are custom -extension Label where Title == Text, Icon == Image { - - public init (_ title: LocalizedStringKey, imageNamed: String) { +public extension Label where Title == Text, Icon == Image { + init(_ title: LocalizedStringKey, imageNamed: String) { if imageNamed.lowercased() == imageNamed { self.init(title, systemImage: imageNamed) - } - else { + } else { self.init(title, image: imageNamed) } } } - diff --git a/Packages/Env/Sources/Env/CustomEnvValues.swift b/Packages/Env/Sources/Env/CustomEnvValues.swift index 935ca262..21e3e2f9 100644 --- a/Packages/Env/Sources/Env/CustomEnvValues.swift +++ b/Packages/Env/Sources/Env/CustomEnvValues.swift @@ -41,7 +41,7 @@ public extension EnvironmentValues { get { self[IsInCaptureMode.self] } set { self[IsInCaptureMode.self] = newValue } } - + var isSupporter: Bool { get { self[IsSupporter.self] } set { self[IsSupporter.self] = newValue } diff --git a/Packages/Env/Sources/Env/Duration.swift b/Packages/Env/Sources/Env/Duration.swift index 72d14845..29340b51 100644 --- a/Packages/Env/Sources/Env/Duration.swift +++ b/Packages/Env/Sources/Env/Duration.swift @@ -36,7 +36,7 @@ public enum Duration: Int, CaseIterable { return "enum.durations.custom" } } - + public static func mutingDurations() -> [Duration] { return Self.allCases.filter { $0 != .custom } } @@ -44,7 +44,7 @@ public enum Duration: Int, CaseIterable { public static func filterDurations() -> [Duration] { return [.infinite, .thirtyMinutes, .oneHour, .sixHours, .twelveHours, .oneDay, .sevenDays, .custom] } - + public static func pollDurations() -> [Duration] { return [.fiveMinutes, .thirtyMinutes, .oneHour, .sixHours, .twelveHours, .oneDay, .threeDays, .sevenDays] } diff --git a/Packages/Env/Sources/Env/Router.swift b/Packages/Env/Sources/Env/Router.swift index b33bce88..d16a1bda 100644 --- a/Packages/Env/Sources/Env/Router.swift +++ b/Packages/Env/Sources/Env/Router.swift @@ -70,7 +70,6 @@ public class RouterPath: ObservableObject { @Published public var path: [RouterDestination] = [] @Published public var presentedSheet: SheetDestination? - public init() {} public func navigate(to: RouterDestination) { diff --git a/Packages/Env/Sources/Env/SoundEffectManager.swift b/Packages/Env/Sources/Env/SoundEffectManager.swift index 69b493c6..1dc69096 100644 --- a/Packages/Env/Sources/Env/SoundEffectManager.swift +++ b/Packages/Env/Sources/Env/SoundEffectManager.swift @@ -1,6 +1,6 @@ +import AVKit import CoreHaptics import UIKit -import AVKit public class SoundEffectManager { public static let shared: SoundEffectManager = .init() @@ -13,7 +13,7 @@ public class SoundEffectManager { } private let userPreferences = UserPreferences.shared - + private var currentPlayer: AVAudioPlayer? private init() {} diff --git a/Packages/Env/Sources/Env/StatusDataController.swift b/Packages/Env/Sources/Env/StatusDataController.swift index 125e3a2a..c221ea82 100644 --- a/Packages/Env/Sources/Env/StatusDataController.swift +++ b/Packages/Env/Sources/Env/StatusDataController.swift @@ -1,18 +1,18 @@ import Foundation -import SwiftUI import Models import Network +import SwiftUI @MainActor public protocol StatusDataControlling: ObservableObject { var isReblogged: Bool { get set } var isBookmarked: Bool { get set } var isFavorited: Bool { get set } - + var favoritesCount: Int { get set } var reblogsCount: Int { get set } var repliesCount: Int { get set } - + func toggleBookmark(remoteStatus: String?) async func toggleReblog(remoteStatus: String?) async func toggleFavorite(remoteStatus: String?) async @@ -21,14 +21,14 @@ public protocol StatusDataControlling: ObservableObject { @MainActor public final class StatusDataControllerProvider { public static let shared = StatusDataControllerProvider() - + private var cache: NSMutableDictionary = [:] - + private struct CacheKey: Hashable { let statusId: String let client: Client } - + public func dataController(for status: any AnyStatus, client: Client) -> StatusDataController { let key = CacheKey(statusId: status.id, client: client) if let controller = cache[key] as? StatusDataController { @@ -38,7 +38,7 @@ public final class StatusDataControllerProvider { cache[key] = controller return controller } - + public func updateDataControllers(for statuses: [Status], client: Client) { for status in statuses { let realStatus: AnyStatus = status.reblog ?? status @@ -52,42 +52,42 @@ public final class StatusDataControllerProvider { public final class StatusDataController: StatusDataControlling { private let status: AnyStatus private let client: Client - + public var isReblogged: Bool public var isBookmarked: Bool public var isFavorited: Bool - + public var favoritesCount: Int public var reblogsCount: Int public var repliesCount: Int - + init(status: AnyStatus, client: Client) { self.status = status self.client = client - - self.isReblogged = status.reblogged == true - self.isBookmarked = status.bookmarked == true - self.isFavorited = status.favourited == true - - self.reblogsCount = status.reblogsCount - self.repliesCount = status.repliesCount - self.favoritesCount = status.favouritesCount + + isReblogged = status.reblogged == true + isBookmarked = status.bookmarked == true + isFavorited = status.favourited == true + + reblogsCount = status.reblogsCount + repliesCount = status.repliesCount + favoritesCount = status.favouritesCount } - + public func updateFrom(status: AnyStatus, publishUpdate: Bool) { - self.isReblogged = status.reblogged == true - self.isBookmarked = status.bookmarked == true - self.isFavorited = status.favourited == true - - self.reblogsCount = status.reblogsCount - self.repliesCount = status.repliesCount - self.favoritesCount = status.favouritesCount - + isReblogged = status.reblogged == true + isBookmarked = status.bookmarked == true + isFavorited = status.favourited == true + + reblogsCount = status.reblogsCount + repliesCount = status.repliesCount + favoritesCount = status.favouritesCount + if publishUpdate { objectWillChange.send() } } - + public func toggleFavorite(remoteStatus: String?) async { guard client.isAuth else { return } isFavorited.toggle() @@ -104,8 +104,7 @@ public final class StatusDataController: StatusDataControlling { objectWillChange.send() } } - - + public func toggleReblog(remoteStatus: String?) async { guard client.isAuth else { return } isReblogged.toggle() @@ -122,7 +121,7 @@ public final class StatusDataController: StatusDataControlling { objectWillChange.send() } } - + public func toggleBookmark(remoteStatus: String?) async { guard client.isAuth else { return } isBookmarked.toggle() diff --git a/Packages/Env/Sources/Env/StatusEmbedCache.swift b/Packages/Env/Sources/Env/StatusEmbedCache.swift index ffbc8bb2..fdfa96d4 100644 --- a/Packages/Env/Sources/Env/StatusEmbedCache.swift +++ b/Packages/Env/Sources/Env/StatusEmbedCache.swift @@ -7,7 +7,7 @@ public class StatusEmbedCache { public static let shared = StatusEmbedCache() private var cache: [URL: Status] = [:] - + public var badStatusesURLs = Set() private init() {} diff --git a/Packages/Env/Sources/Env/UserPreferences.swift b/Packages/Env/Sources/Env/UserPreferences.swift index 57f6cfc5..3843b02e 100644 --- a/Packages/Env/Sources/Env/UserPreferences.swift +++ b/Packages/Env/Sources/Env/UserPreferences.swift @@ -49,7 +49,7 @@ public class UserPreferences: ObservableObject { @AppStorage("swipeactions-icon-style") public var swipeActionsIconStyle: SwipeActionsIconStyle = .iconWithText @AppStorage("requested_review") public var requestedReview = false - + @AppStorage("collapse-long-posts") public var collapseLongPosts = true public enum SwipeActionsIconStyle: String, CaseIterable { @@ -70,7 +70,7 @@ public class UserPreferences: ObservableObject { // Main actor-isolated static property 'allCases' cannot be used to // satisfy nonisolated protocol requirement // - nonisolated public static var allCases: [Self] { + public nonisolated static var allCases: [Self] { [.iconWithText, .iconOnly] } } diff --git a/Packages/Explore/Sources/Explore/ExploreView.swift b/Packages/Explore/Sources/Explore/ExploreView.swift index 879dad6b..ad11387d 100644 --- a/Packages/Explore/Sources/Explore/ExploreView.swift +++ b/Packages/Explore/Sources/Explore/ExploreView.swift @@ -127,12 +127,13 @@ public struct ExploreView: View { private var suggestedAccountsSection: some View { Section("explore.section.suggested-users") { ForEach(viewModel.suggestedAccounts - .prefix(upTo: viewModel.suggestedAccounts.count > 3 ? 3 : viewModel.suggestedAccounts.count)) { account in - if let relationship = viewModel.suggestedAccountsRelationShips.first(where: { $0.id == account.id }) { - AccountsListRow(viewModel: .init(account: account, relationShip: relationship)) - .listRowBackground(theme.primaryBackgroundColor) - } + .prefix(upTo: viewModel.suggestedAccounts.count > 3 ? 3 : viewModel.suggestedAccounts.count)) + { account in + if let relationship = viewModel.suggestedAccountsRelationShips.first(where: { $0.id == account.id }) { + AccountsListRow(viewModel: .init(account: account, relationShip: relationship)) + .listRowBackground(theme.primaryBackgroundColor) } + } NavigationLink(value: RouterDestination.accountsList(accounts: viewModel.suggestedAccounts)) { Text("see-more") .foregroundColor(theme.tintColor) @@ -144,11 +145,12 @@ public struct ExploreView: View { private var trendingTagsSection: some View { Section("explore.section.trending.tags") { ForEach(viewModel.trendingTags - .prefix(upTo: viewModel.trendingTags.count > 5 ? 5 : viewModel.trendingTags.count)) { tag in - TagRowView(tag: tag) - .listRowBackground(theme.primaryBackgroundColor) - .padding(.vertical, 4) - } + .prefix(upTo: viewModel.trendingTags.count > 5 ? 5 : viewModel.trendingTags.count)) + { tag in + TagRowView(tag: tag) + .listRowBackground(theme.primaryBackgroundColor) + .padding(.vertical, 4) + } NavigationLink(value: RouterDestination.tagsList(tags: viewModel.trendingTags)) { Text("see-more") .foregroundColor(theme.tintColor) @@ -160,11 +162,12 @@ public struct ExploreView: View { private var trendingPostsSection: some View { Section("explore.section.trending.posts") { ForEach(viewModel.trendingStatuses - .prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) { status in - StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) }) - .listRowBackground(theme.primaryBackgroundColor) - .padding(.vertical, 8) - } + .prefix(upTo: viewModel.trendingStatuses.count > 3 ? 3 : viewModel.trendingStatuses.count)) + { status in + StatusRowView(viewModel: { .init(status: status, client: client, routerPath: routerPath) }) + .listRowBackground(theme.primaryBackgroundColor) + .padding(.vertical, 8) + } NavigationLink(value: RouterDestination.trendingTimeline) { Text("see-more") @@ -177,11 +180,12 @@ public struct ExploreView: View { private var trendingLinksSection: some View { Section("explore.section.trending.links") { ForEach(viewModel.trendingLinks - .prefix(upTo: viewModel.trendingLinks.count > 3 ? 3 : viewModel.trendingLinks.count)) { card in - StatusRowCardView(card: card) - .listRowBackground(theme.primaryBackgroundColor) - .padding(.vertical, 8) - } + .prefix(upTo: viewModel.trendingLinks.count > 3 ? 3 : viewModel.trendingLinks.count)) + { card in + StatusRowCardView(card: card) + .listRowBackground(theme.primaryBackgroundColor) + .padding(.vertical, 8) + } NavigationLink { List { ForEach(viewModel.trendingLinks) { card in diff --git a/Packages/Explore/Sources/Explore/TagsListView.swift b/Packages/Explore/Sources/Explore/TagsListView.swift index 60375bb7..f8856efc 100644 --- a/Packages/Explore/Sources/Explore/TagsListView.swift +++ b/Packages/Explore/Sources/Explore/TagsListView.swift @@ -1,16 +1,16 @@ -import SwiftUI -import Models import DesignSystem +import Models +import SwiftUI public struct TagsListView: View { @EnvironmentObject private var theme: Theme - + let tags: [Tag] - + public init(tags: [Tag]) { self.tags = tags } - + public var body: some View { List { ForEach(tags) { tag in diff --git a/Packages/Models/Sources/Models/ServerError.swift b/Packages/Models/Sources/Models/ServerError.swift index 5b51414a..a8a17724 100644 --- a/Packages/Models/Sources/Models/ServerError.swift +++ b/Packages/Models/Sources/Models/ServerError.swift @@ -2,6 +2,7 @@ import Foundation public struct ServerError: Decodable, Error { public let error: String? + public var httpCode: Int } extension ServerError: Sendable {} diff --git a/Packages/Models/Sources/Models/ServerFilter.swift b/Packages/Models/Sources/Models/ServerFilter.swift index f6dd556a..ce090b45 100644 --- a/Packages/Models/Sources/Models/ServerFilter.swift +++ b/Packages/Models/Sources/Models/ServerFilter.swift @@ -22,14 +22,14 @@ public struct ServerFilter: Codable, Identifiable, Hashable, Sendable { public let context: [Context] public let expiresIn: Int? public let expiresAt: ServerDate? - + public func hasExpiry() -> Bool { return expiresAt != nil } - + public func isExpired() -> Bool { if let expiresAtDate = expiresAt?.asDate { - return expiresAtDate < Date() + return expiresAtDate < Date() } else { return false } diff --git a/Packages/Models/Sources/Models/Status.swift b/Packages/Models/Sources/Models/Status.swift index 84196392..5dcbe5ab 100644 --- a/Packages/Models/Sources/Models/Status.swift +++ b/Packages/Models/Sources/Models/Status.swift @@ -103,7 +103,6 @@ public final class Status: AnyStatus, Codable, Identifiable, Equatable, Hashable public let sensitive: Bool public let language: String? - public init(id: String, content: HTMLString, account: Account, createdAt: ServerDate, editedAt: ServerDate?, reblog: ReblogStatus?, mediaAttachments: [MediaAttachment], mentions: [Mention], repliesCount: Int, reblogsCount: Int, favouritesCount: Int, card: Card?, favourited: Bool?, reblogged: Bool?, pinned: Bool?, bookmarked: Bool?, emojis: [Emoji], url: String?, application: Application?, inReplyToId: String?, inReplyToAccountId: String?, visibility: Visibility, poll: Poll?, spoilerText: HTMLString, filtered: [Filtered]?, sensitive: Bool, language: String?) { self.id = id self.content = content @@ -277,5 +276,3 @@ extension Status: Sendable {} // Every property in ReblogStatus is immutable. extension ReblogStatus: Sendable {} - - diff --git a/Packages/Network/Sources/Network/Client.swift b/Packages/Network/Sources/Network/Client.swift index 2c54643c..567eca0c 100644 --- a/Packages/Network/Sources/Network/Client.swift +++ b/Packages/Network/Sources/Network/Client.swift @@ -1,8 +1,8 @@ import Combine import Foundation import Models -import SwiftUI import os +import SwiftUI public final class Client: ObservableObject, Equatable, Identifiable, Hashable { public static func == (lhs: Client, rhs: Client) -> Bool { @@ -61,7 +61,7 @@ public final class Client: ObservableObject, Equatable, Identifiable, Hashable { public init(server: String, version: Version = .v1, oauthToken: OauthToken? = nil) { self.server = server self.version = version - self.critical = .init(initialState: Critical(oauthToken: oauthToken, connections: [server])) + critical = .init(initialState: Critical(oauthToken: oauthToken, connections: [server])) urlSession = URLSession.shared decoder.keyDecodingStrategy = .convertFromSnakeCase } @@ -141,7 +141,7 @@ public final class Client: ObservableObject, Equatable, Identifiable, Hashable { linkHandler = .init(rawLink: link) } logResponseOnError(httpResponse: httpResponse, data: data) - return (try decoder.decode(Entity.self, from: data), linkHandler) + return try (decoder.decode(Entity.self, from: data), linkHandler) } public func post(endpoint: Endpoint, forceVersion: Version? = nil) async throws -> Entity { @@ -184,7 +184,10 @@ public final class Client: ObservableObject, Equatable, Identifiable, Hashable { do { return try decoder.decode(Entity.self, from: data) } catch { - if let serverError = try? decoder.decode(ServerError.self, from: data) { + if var serverError = try? decoder.decode(ServerError.self, from: data) { + if let httpResponse = httpResponse as? HTTPURLResponse { + serverError.httpCode = httpResponse.statusCode + } throw serverError } throw error diff --git a/Packages/Network/Sources/Network/Endpoint/Oauth.swift b/Packages/Network/Sources/Network/Endpoint/Oauth.swift index 4a5e4b71..edcc6808 100644 --- a/Packages/Network/Sources/Network/Endpoint/Oauth.swift +++ b/Packages/Network/Sources/Network/Endpoint/Oauth.swift @@ -13,7 +13,7 @@ public enum Oauth: Endpoint { return "oauth/token" } } - + public var jsonValue: Encodable? { switch self { case let .token(code, clientId, clientSecret): @@ -22,7 +22,7 @@ public enum Oauth: Endpoint { return nil } } - + public struct TokenData: Encodable { public let grantType = "authorization_code" public let clientId: String diff --git a/Packages/Network/Sources/Network/OpenAIClient.swift b/Packages/Network/Sources/Network/OpenAIClient.swift index 7bb3ebb0..40408c0a 100644 --- a/Packages/Network/Sources/Network/OpenAIClient.swift +++ b/Packages/Network/Sources/Network/OpenAIClient.swift @@ -30,28 +30,28 @@ public struct OpenAIClient { decoder.keyDecodingStrategy = .convertFromSnakeCase return decoder } - + public struct ChatRequest: OpenAIRequest { public struct Message: Encodable { public let role = "user" public let content: String } - + let model = "gpt-3.5-turbo" let messages: [Message] - + let temperature: CGFloat - + var path: String { "chat/completions" } public init(content: String, temperature: CGFloat) { - self.messages = [.init(content: content)] + messages = [.init(content: content)] self.temperature = temperature } } - + public enum Prompt { case correct(input: String) case shorten(input: String) @@ -81,7 +81,7 @@ public struct OpenAIClient { public let role: String public let content: String } - + public let message: Message? } diff --git a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift index ed5143f6..9aded4aa 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift @@ -47,23 +47,23 @@ extension Models.Notification.NotificationType { func icon(isPrivate: Bool) -> Image { if isPrivate { - return Image(systemName:"tray.fill") + return Image(systemName: "tray.fill") } switch self { case .status: - return Image(systemName:"pencil") + return Image(systemName: "pencil") case .mention: - return Image(systemName:"at") + return Image(systemName: "at") case .reblog: return Image("Rocket.Fill") case .follow, .follow_request: - return Image(systemName:"person.fill.badge.plus") + return Image(systemName: "person.fill.badge.plus") case .favourite: - return Image(systemName:"star.fill") + return Image(systemName: "star.fill") case .poll: - return Image(systemName:"chart.bar.fill") + return Image(systemName: "chart.bar.fill") case .update: - return Image(systemName:"pencil.line") + return Image(systemName: "pencil.line") } } diff --git a/Packages/Notifications/Sources/Notifications/NotificationsListView.swift b/Packages/Notifications/Sources/Notifications/NotificationsListView.swift index 65556877..94f763a4 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationsListView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationsListView.swift @@ -145,7 +145,8 @@ public struct NotificationsListView: View { case .error: ErrorView(title: "notifications.error.title", message: "notifications.error.message", - buttonTitle: "action.retry") { + buttonTitle: "action.retry") + { Task { await viewModel.fetchNotifications() } diff --git a/Packages/Status/Sources/Status/Detail/StatusDetailView.swift b/Packages/Status/Sources/Status/Detail/StatusDetailView.swift index 201f7d49..d60d0bb7 100644 --- a/Packages/Status/Sources/Status/Detail/StatusDetailView.swift +++ b/Packages/Status/Sources/Status/Detail/StatusDetailView.swift @@ -155,7 +155,8 @@ public struct StatusDetailView: View { private var errorView: some View { ErrorView(title: "status.error.title", message: "status.error.message", - buttonTitle: "action.retry") { + buttonTitle: "action.retry") + { Task { await viewModel.fetch() } diff --git a/Packages/Status/Sources/Status/Detail/StatusDetailViewModel.swift b/Packages/Status/Sources/Status/Detail/StatusDetailViewModel.swift index a1f5892e..c50ca806 100644 --- a/Packages/Status/Sources/Status/Detail/StatusDetailViewModel.swift +++ b/Packages/Status/Sources/Status/Detail/StatusDetailViewModel.swift @@ -1,8 +1,8 @@ +import Env import Foundation import Models import Network import SwiftUI -import Env @MainActor class StatusDetailViewModel: ObservableObject { @@ -79,9 +79,9 @@ class StatusDetailViewModel: ObservableObject { var statuses = data.context.ancestors statuses.append(data.status) statuses.append(contentsOf: data.context.descendants) - + StatusDataControllerProvider.shared.updateDataControllers(for: statuses, client: client) - + if animate { withAnimation { isLoadingContext = false diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorAccessoryView.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorAccessoryView.swift index 457bfeac..87bc9ec2 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorAccessoryView.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorAccessoryView.swift @@ -51,14 +51,14 @@ struct StatusEditorAccessoryView: View { matching: .any(of: [.images, .videos])) .fileImporter(isPresented: $isFileImporterPresented, allowedContentTypes: [.image, .video], - allowsMultipleSelection: true) { result in + allowsMultipleSelection: true) + { result in if let urls = try? result.get() { viewModel.processURLs(urls: urls) } } .accessibilityLabel("accessibility.editor.button.attach-photo") .disabled(viewModel.showPoll) - Button { withAnimation { diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorCompressor.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorCompressor.swift index 96896424..e0a30457 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorCompressor.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorCompressor.swift @@ -1,86 +1,87 @@ +import AVFoundation import Foundation import UIKit -import AVFoundation actor StatusEditorCompressor { enum CompressorError: Error { case noData } - + func compressImageFrom(url: URL) async -> Data? { - return await withCheckedContinuation{ continuation in + return await withCheckedContinuation { continuation in let sourceOptions = [kCGImageSourceShouldCache: false] as CFDictionary guard let source = CGImageSourceCreateWithURL(url as CFURL, sourceOptions) else { continuation.resume(returning: nil) return } - + let maxPixelSize: Int if Bundle.main.bundlePath.hasSuffix(".appex") { maxPixelSize = 1536 } else { maxPixelSize = 4096 } - + let downsampleOptions = [ kCGImageSourceCreateThumbnailFromImageAlways: true, kCGImageSourceCreateThumbnailWithTransform: true, kCGImageSourceThumbnailMaxPixelSize: maxPixelSize, - ] as [CFString : Any] as CFDictionary - + ] as [CFString: Any] as CFDictionary + guard let cgImage = CGImageSourceCreateThumbnailAtIndex(source, 0, downsampleOptions) else { continuation.resume(returning: nil) return } - + let data = NSMutableData() guard let imageDestination = CGImageDestinationCreateWithData(data, UTType.jpeg.identifier as CFString, 1, nil) else { continuation.resume(returning: nil) return } - + let isPNG: Bool = { guard let utType = cgImage.utType else { return false } return (utType as String) == UTType.png.identifier }() - + let destinationProperties = [ - kCGImageDestinationLossyCompressionQuality: isPNG ? 1.0 : 0.75 + kCGImageDestinationLossyCompressionQuality: isPNG ? 1.0 : 0.75, ] as CFDictionary - + CGImageDestinationAddImage(imageDestination, cgImage, destinationProperties) CGImageDestinationFinalize(imageDestination) - + continuation.resume(returning: data as Data) } } - + func compressImageForUpload(_ image: UIImage) async throws -> Data { var image = image if image.size.height > 5000 || image.size.width > 5000 { image = image.resized(to: .init(width: image.size.width / 4, height: image.size.height / 4)) } - + guard var imageData = image.jpegData(compressionQuality: 0.8) else { throw CompressorError.noData } - - let maxSize: Int = 10 * 1024 * 1024 + + let maxSize = 10 * 1024 * 1024 if imageData.count > maxSize { while imageData.count > maxSize { guard let compressedImage = UIImage(data: imageData), - let compressedData = compressedImage.jpegData(compressionQuality: 0.8) else { + let compressedData = compressedImage.jpegData(compressionQuality: 0.8) + else { throw CompressorError.noData } imageData = compressedData } } - + return imageData } - + func compressVideo(_ url: URL) async -> URL? { await withCheckedContinuation { continuation in let urlAsset = AVURLAsset(url: url, options: nil) @@ -97,5 +98,4 @@ actor StatusEditorCompressor { } } } - } diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift index 4c992fda..389cfcdd 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift @@ -31,11 +31,11 @@ enum StatusEditorUTTypeSupported: String, CaseIterable { // Main actor-isolated static property 'allCases' cannot be used to // satisfy nonisolated protocol requirement // - nonisolated public static var allCases: [StatusEditorUTTypeSupported] { + public nonisolated static var allCases: [StatusEditorUTTypeSupported] { [.url, .text, .plaintext, .image, .jpeg, .png, .tiff, .video, .movie, .mp4, .gif, .gif2, .quickTimeMovie, .uiimage, .adobeRawImage] } - + static func types() -> [UTType] { [.url, .text, .plainText, .image, .jpeg, .png, .tiff, .video, .mpeg4Movie, .gif, .movie, .quickTimeMovie] } diff --git a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift index f5398bd8..f26ad862 100644 --- a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift +++ b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift @@ -170,7 +170,7 @@ public struct StatusEditorView: View { @ViewBuilder private var languageConfirmationDialog: some View { - if let (detected: detected, selected: selected) = viewModel.languageConfirmationDialogLanguages, + if let (detected: detected, selected: selected) = viewModel.languageConfirmationDialogLanguages, let detectedLong = Locale.current.localizedString(forLanguageCode: detected), let selectedLong = Locale.current.localizedString(forLanguageCode: selected) { diff --git a/Packages/Status/Sources/Status/Editor/StatusEditorViewModel.swift b/Packages/Status/Sources/Status/Editor/StatusEditorViewModel.swift index b113938e..31fdba19 100644 --- a/Packages/Status/Sources/Status/Editor/StatusEditorViewModel.swift +++ b/Packages/Status/Sources/Status/Editor/StatusEditorViewModel.swift @@ -20,6 +20,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject { } } } + var theme: Theme? var preferences: UserPreferences? var languageConfirmationDialogLanguages: (detected: String, selected: String)? @@ -69,7 +70,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject { var statusTextCharacterLength: Int { urlLengthAdjustments - statusText.string.utf16.count - spoilerTextCount } - + private var itemsProvider: [NSItemProvider]? @Published var backupStatusText: NSAttributedString? @@ -135,7 +136,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject { } private var mentionString: String? - + private var uploadTask: Task? private var suggestedTask: Task? @@ -363,11 +364,11 @@ public class StatusEditorViewModel: NSObject, ObservableObject { } // MARK: - Shar sheet / Item provider - + func processURLs(urls: [URL]) { isMediasLoading = true let items = urls.filter { $0.startAccessingSecurityScopedResource() } - .compactMap { NSItemProvider(contentsOf: $0) } + .compactMap { NSItemProvider(contentsOf: $0) } processItemsProvider(items: items) } @@ -391,7 +392,8 @@ public class StatusEditorViewModel: NSObject, ObservableObject { error: nil)) } else if let content = content as? ImageFileTranseferable, let compressedData = await compressor.compressImageFrom(url: content.url), - let image = UIImage(data: compressedData) { + let image = UIImage(data: compressedData) + { mediasImages.append(.init(image: image, movieTransferable: nil, gifTransferable: nil, @@ -616,7 +618,8 @@ public class StatusEditorViewModel: NSObject, ObservableObject { } } else if let videoURL = originalContainer.movieTransferable?.url, let compressedVideoURL = await compressor.compressVideo(videoURL), - let data = try? Data(contentsOf: compressedVideoURL) { + let data = try? Data(contentsOf: compressedVideoURL) + { let uploadedMedia = try await uploadMedia(data: data, mimeType: compressedVideoURL.mimeType()) mediasImages[index] = .init(image: mode.isInShareExtension ? originalContainer.image : nil, movieTransferable: originalContainer.movieTransferable, diff --git a/Packages/Status/Sources/Status/List/StatusesListView.swift b/Packages/Status/Sources/Status/List/StatusesListView.swift index 460139d3..efae9440 100644 --- a/Packages/Status/Sources/Status/List/StatusesListView.swift +++ b/Packages/Status/Sources/Status/List/StatusesListView.swift @@ -7,22 +7,23 @@ import SwiftUI public struct StatusesListView: View where Fetcher: StatusesFetcher { @EnvironmentObject private var theme: Theme - + @ObservedObject private var fetcher: Fetcher private let isRemote: Bool private let routerPath: RouterPath private let client: Client - + public init(fetcher: Fetcher, client: Client, routerPath: RouterPath, - isRemote: Bool = false) { + isRemote: Bool = false) + { self.fetcher = fetcher self.isRemote = isRemote self.client = client self.routerPath = routerPath } - + public var body: some View { switch fetcher.statusesState { case .loading: @@ -33,29 +34,30 @@ public struct StatusesListView: View where Fetcher: StatusesFetcher { case .error: ErrorView(title: "status.error.title", message: "status.error.loading.message", - buttonTitle: "action.retry") { + buttonTitle: "action.retry") + { Task { await fetcher.fetchNewestStatuses() } } - .listRowBackground(theme.primaryBackgroundColor) - .listRowSeparator(.hidden) - + .listRowBackground(theme.primaryBackgroundColor) + .listRowSeparator(.hidden) + case let .display(statuses, nextPageState): ForEach(statuses, id: \.viewId) { status in StatusRowView(viewModel: { StatusRowViewModel(status: status, client: client, routerPath: routerPath, isRemote: isRemote) - - }) - .id(status.id) - .onAppear { - fetcher.statusDidAppear(status: status) - } - .onDisappear { - fetcher.statusDidDisappear(status: status) - } + + }) + .id(status.id) + .onAppear { + fetcher.statusDidAppear(status: status) + } + .onDisappear { + fetcher.statusDidDisappear(status: status) + } } switch nextPageState { case .hasNextPage: @@ -72,7 +74,7 @@ public struct StatusesListView: View where Fetcher: StatusesFetcher { } } } - + private var loadingRow: some View { HStack { Spacer() diff --git a/Packages/Status/Sources/Status/Media/VideoPlayerView.swift b/Packages/Status/Sources/Status/Media/VideoPlayerView.swift index 3785c8b3..add995ae 100644 --- a/Packages/Status/Sources/Status/Media/VideoPlayerView.swift +++ b/Packages/Status/Sources/Status/Media/VideoPlayerView.swift @@ -22,7 +22,8 @@ class VideoPlayerViewModel: ObservableObject { } guard let player else { return } NotificationCenter.default.addObserver(forName: .AVPlayerItemDidPlayToEndTime, - object: player.currentItem, queue: .main) { [weak self] _ in + object: player.currentItem, queue: .main) + { [weak self] _ in if autoPlay { self?.player?.seek(to: CMTime.zero) self?.player?.play() diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index 2d99b536..2fa171a8 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -10,20 +10,20 @@ public struct StatusRowView: View { @Environment(\.isInCaptureMode) private var isInCaptureMode: Bool @Environment(\.redactionReasons) private var reasons @Environment(\.isCompact) private var isCompact: Bool - + @EnvironmentObject private var theme: Theme - + @StateObject var viewModel: StatusRowViewModel - + // StateObject accepts an @autoclosure which only allocates the view model once when the view gets on screen. public init(viewModel: @escaping () -> StatusRowViewModel) { _viewModel = StateObject(wrappedValue: viewModel()) } - + var contextMenu: some View { StatusRowContextMenu(viewModel: viewModel) } - + public var body: some View { VStack(alignment: .leading) { if viewModel.isFiltered, let filter = viewModel.filter { @@ -151,7 +151,7 @@ public struct StatusRowView: View { client: viewModel.client) ) } - + @ViewBuilder private var accesibilityActions: some View { // Add the individual mentions as accessibility actions @@ -160,20 +160,20 @@ public struct StatusRowView: View { viewModel.routerPath.navigate(to: .accountDetail(id: mention.id)) } } - + Button(viewModel.displaySpoiler ? "status.show-more" : "status.show-less") { withAnimation { viewModel.displaySpoiler.toggle() } } - + Button("@\(viewModel.status.account.username)") { viewModel.routerPath.navigate(to: .accountDetail(id: viewModel.status.account.id)) } - + contextMenu } - + private func makeFilterView(filter: Filter) -> some View { HStack { Text("status.filter.filtered-by-\(filter.title)") @@ -186,7 +186,7 @@ public struct StatusRowView: View { } } } - + private var remoteContentLoadingView: some View { ZStack(alignment: .center) { VStack { diff --git a/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift b/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift index 329d5be9..786ca020 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift @@ -1,10 +1,10 @@ import Combine +import DesignSystem import Env import Models import NaturalLanguage import Network import SwiftUI -import DesignSystem @MainActor public class StatusRowViewModel: ObservableObject { @@ -39,25 +39,26 @@ public class StatusRowViewModel: ObservableObject { recalcCollapse() } } + // number of lines to show, nil means show the whole post @Published var lineLimit: Int? = nil // post length determining if the post should be collapsed - let collapseThresholdLength : Int = 750 + let collapseThresholdLength: Int = 750 // number of text lines to show on a collpased post let collapsedLines: Int = 8 // user preference, set in init var collapseLongPosts: Bool = false - + private func recalcCollapse() { let hasContentWarning = !status.spoilerText.asRawText.isEmpty let showCollapseButton = collapseLongPosts && isCollapsed && !hasContentWarning - && finalStatus.content.asRawText.unicodeScalars.count > collapseThresholdLength + && finalStatus.content.asRawText.unicodeScalars.count > collapseThresholdLength let newlineLimit = showCollapseButton && isCollapsed ? collapsedLines : nil if newlineLimit != lineLimit { lineLimit = newlineLimit } } - + private let theme = Theme.shared private let userMentionned: Bool @@ -94,7 +95,7 @@ public class StatusRowViewModel: ObservableObject { textDisabled: Bool = false) { self.status = status - self.finalStatus = status.reblog ?? status + finalStatus = status.reblog ?? status self.client = client self.routerPath = routerPath self.isFocused = isFocused @@ -112,13 +113,12 @@ public class StatusRowViewModel: ObservableObject { displaySpoiler = !finalStatus.spoilerText.asRawText.isEmpty } - if status.mentions.first(where: { $0.id == CurrentAccount.shared.account?.id }) != nil { userMentionned = true } else { userMentionned = false } - + isFiltered = filter != nil if let url = embededStatusURL(), @@ -127,7 +127,7 @@ public class StatusRowViewModel: ObservableObject { isEmbedLoading = false embeddedStatus = embed } - + collapseLongPosts = UserPreferences.shared.collapseLongPosts recalcCollapse() } @@ -187,7 +187,8 @@ public class StatusRowViewModel: ObservableObject { if !content.statusesURLs.isEmpty, let url = content.statusesURLs.first, !StatusEmbedCache.shared.badStatusesURLs.contains(url), - client.hasConnection(with: url) { + client.hasConnection(with: url) + { return url } return nil @@ -202,7 +203,7 @@ public class StatusRowViewModel: ObservableObject { } return } - + if let embed = StatusEmbedCache.shared.get(url: url) { isEmbedLoading = false embeddedStatus = embed @@ -224,8 +225,7 @@ public class StatusRowViewModel: ObservableObject { } if let embed { StatusEmbedCache.shared.set(url: url, status: embed) - } - else { + } else { StatusEmbedCache.shared.badStatusesURLs.insert(url) } withAnimation { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift index 5c788750..5e3a7b95 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift @@ -24,7 +24,7 @@ struct StatusRowActionsView: View { // Main actor-isolated static property 'allCases' cannot be used to // satisfy nonisolated protocol requirement // - nonisolated public static var allCases: [StatusRowActionsView.Action] { + public nonisolated static var allCases: [StatusRowActionsView.Action] { [.respond, .boost, .favorite, .bookmark, .share] } @@ -99,7 +99,8 @@ struct StatusRowActionsView: View { { ShareLink(item: url, subject: Text(viewModel.finalStatus.account.safeDisplayName), - message: Text(viewModel.finalStatus.content.asRawText)) { + message: Text(viewModel.finalStatus.content.asRawText)) + { action.image(dataController: statusDataController) } .buttonStyle(.statusAction()) @@ -142,7 +143,8 @@ struct StatusRowActionsView: View { (viewModel.status.visibility == .direct || viewModel.status.visibility == .priv && viewModel.status.account.id != currentAccount.account?.id)) if let count = action.count(dataController: statusDataController, viewModel: viewModel, - theme: theme), !viewModel.isRemote { + theme: theme), !viewModel.isRemote + { Text("\(count)") .foregroundColor(Color(UIColor.secondaryLabel)) .font(.scaledFootnote) @@ -150,7 +152,6 @@ struct StatusRowActionsView: View { } } } - private func handleAction(action: Action) { Task { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift index 04c4f3ea..1816a629 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift @@ -71,7 +71,8 @@ struct StatusRowContextMenu: View { { ShareLink(item: url, subject: Text(viewModel.status.reblog?.account.safeDisplayName ?? viewModel.status.account.safeDisplayName), - message: Text(viewModel.status.reblog?.content.asRawText ?? viewModel.status.content.asRawText)) { + message: Text(viewModel.status.reblog?.content.asRawText ?? viewModel.status.content.asRawText)) + { Label("status.action.share", systemImage: "square.and.arrow.up") } diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift index c31f3b22..b34bc802 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowDetailView.swift @@ -5,7 +5,7 @@ import SwiftUI struct StatusRowDetailView: View { @Environment(\.openURL) private var openURL - + @EnvironmentObject private var statusDataController: StatusDataController @ObservedObject var viewModel: StatusRowViewModel diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift index f611ed4c..9e3916c8 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowMediaPreviewView.swift @@ -124,7 +124,8 @@ public struct StatusRowMediaPreviewView: View { } } .alert("status.editor.media.image-description", - isPresented: $isAltAlertDisplayed) { + isPresented: $isAltAlertDisplayed) + { Button("alert.button.ok", action: {}) } message: { Text(altTextDisplayed ?? "") diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift index 68919051..b50b4b45 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift @@ -109,9 +109,9 @@ struct StatusRowSwipeView: View { isBookmarked: statusDataController.isBookmarked, privateBoost: privateBoost), imageNamed: action.iconName(isReblogged: statusDataController.isReblogged, - isFavorited: statusDataController.isFavorited, - isBookmarked: statusDataController.isBookmarked, - privateBoost: privateBoost)) + isFavorited: statusDataController.isFavorited, + isBookmarked: statusDataController.isBookmarked, + privateBoost: privateBoost)) .labelStyle(.iconOnly) .environment(\.symbolVariants, .none) case .iconWithText: @@ -120,9 +120,9 @@ struct StatusRowSwipeView: View { isBookmarked: statusDataController.isBookmarked, privateBoost: privateBoost), imageNamed: action.iconName(isReblogged: statusDataController.isReblogged, - isFavorited: statusDataController.isFavorited, - isBookmarked: statusDataController.isBookmarked, - privateBoost: privateBoost)) + isFavorited: statusDataController.isFavorited, + isBookmarked: statusDataController.isBookmarked, + privateBoost: privateBoost)) .labelStyle(.titleAndIcon) .environment(\.symbolVariants, .none) } diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift index 796b62ef..a389d55d 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift @@ -7,7 +7,7 @@ struct StatusRowTextView: View { @EnvironmentObject private var theme: Theme @ObservedObject var viewModel: StatusRowViewModel - + var body: some View { VStack { HStack { diff --git a/Packages/Timeline/Sources/Timeline/TimelineCache.swift b/Packages/Timeline/Sources/Timeline/TimelineCache.swift index 46ea3047..3670e1d6 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineCache.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineCache.swift @@ -34,7 +34,7 @@ public actor TimelineCache { try await engine.removeAllData() let itemKeys = statuses.map { CacheKey($0[keyPath: \.id]) } let dataAndKeys = try zip(itemKeys, statuses) - .map { (key: $0, data: try encoder.encode($1)) } + .map { try (key: $0, data: encoder.encode($1)) } try await engine.write(dataAndKeys) } catch {} } diff --git a/Packages/Timeline/Sources/Timeline/TimelineDatasource.swift b/Packages/Timeline/Sources/Timeline/TimelineDatasource.swift index 0d01141f..5b37e8cc 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineDatasource.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineDatasource.swift @@ -9,7 +9,7 @@ actor TimelineDatasource { } func get() -> [Status] { - statuses.filter{ $0.filtered?.first?.filter.filterAction != .hide } + statuses.filter { $0.filtered?.first?.filter.filterAction != .hide } } func reset() { diff --git a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift index 45288687..2fa4c129 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift @@ -162,7 +162,7 @@ extension TimelineViewModel: StatusesFetcher { } await fetchNewestStatuses() } - + func fetchNewestStatuses() async { guard let client else { return } do {