diff --git a/IceCubesApp/App/IceCubesApp.swift b/IceCubesApp/App/IceCubesApp.swift index 48318f68..31abe646 100644 --- a/IceCubesApp/App/IceCubesApp.swift +++ b/IceCubesApp/App/IceCubesApp.swift @@ -62,7 +62,8 @@ struct IceCubesApp: App { pushNotificationsService.handledNotification = nil if appAccountsManager.currentAccount.oauthToken?.accessToken != notification?.account.token.accessToken, let account = appAccountsManager.availableAccounts.first(where: - { $0.oauthToken?.accessToken == notification?.account.token.accessToken }) { + { $0.oauthToken?.accessToken == notification?.account.token.accessToken }) + { appAccountsManager.currentAccount = account DispatchQueue.main.asyncAfter(deadline: .now() + 0.2) { selectedTab = .notifications @@ -143,7 +144,7 @@ struct IceCubesApp: App { sideBarLoadedTabs.removeAll() } } - + private var notificationsSecondaryColumn: some View { NotificationsTab(popToRootTab: $popToRootTab, lockedType: nil) .environment(\.isSecondaryColumn, true) diff --git a/IceCubesApp/App/Report/ReportView.swift b/IceCubesApp/App/Report/ReportView.swift index eb11abe9..c70b905a 100644 --- a/IceCubesApp/App/Report/ReportView.swift +++ b/IceCubesApp/App/Report/ReportView.swift @@ -1,24 +1,24 @@ -import SwiftUI -import Models -import Env import DesignSystem -import Status +import Env +import Models import Network +import Status +import SwiftUI public struct ReportView: View { @Environment(\.dismiss) private var dismiss - + @EnvironmentObject private var theme: Theme @EnvironmentObject private var client: Client - + let status: Status @State private var commentText: String = "" @State private var isSendingReport: Bool = false - + struct ReportSent: Decodable { - let id : String + let id: String } - + public var body: some View { NavigationStack { Form { @@ -28,7 +28,7 @@ public struct ReportView: View { axis: .vertical) } .listRowBackground(theme.primaryBackgroundColor) - + StatusEmbeddedView(status: status, client: .init(server: ""), routerPath: RouterPath()) .allowsHitTesting(false) .listRowBackground(theme.primaryBackgroundColor) @@ -45,9 +45,9 @@ public struct ReportView: View { Task { do { let _: ReportSent = - try await client.post(endpoint: Statuses.report(accountId: status.account.id, - statusId: status.id, - comment: commentText)) + try await client.post(endpoint: Statuses.report(accountId: status.account.id, + statusId: status.id, + comment: commentText)) dismiss() isSendingReport = false } catch { @@ -62,7 +62,7 @@ public struct ReportView: View { } } } - + ToolbarItem(placement: .navigationBarLeading) { Button { dismiss() diff --git a/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift b/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift index 22161cd1..309e84b2 100644 --- a/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/ContentSettingsView.swift @@ -21,7 +21,7 @@ struct ContentSettingsView: View { Section("settings.content.media") { Toggle(isOn: $userPreferences.showAltTextForMedia) { - Text("settings.content.media.show.alt") + Text("settings.content.media.show.alt") } }.listRowBackground(theme.primaryBackgroundColor) @@ -69,7 +69,6 @@ struct ContentSettingsView: View { } .listRowBackground(theme.primaryBackgroundColor) - } .navigationTitle("settings.content.navigation-title") .scrollContentBackground(.hidden) diff --git a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift index 33f7fe1a..eed96c26 100644 --- a/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift +++ b/IceCubesApp/App/Tabs/Settings/DisplaySettingsView.swift @@ -1,9 +1,9 @@ import DesignSystem import Env import Models +import Network import Status import SwiftUI -import Network struct DisplaySettingsView: View { typealias FontState = Theme.FontState @@ -67,10 +67,10 @@ struct DisplaySettingsView: View { } } .navigationDestination(isPresented: $isFontSelectorPresented, destination: { FontPicker() }) - + Toggle("settings.display.font.rounded", isOn: $userPreferences.useSFRoundedFont) .disabled(userPreferences.chosenFont != nil) - + VStack { Slider(value: $userPreferences.fontSizeScale, in: 0.5 ... 1.5, step: 0.1) Text("settings.display.font.scaling-\(String(format: "%.1f", userPreferences.fontSizeScale))") @@ -81,7 +81,7 @@ struct DisplaySettingsView: View { } } .listRowBackground(theme.primaryBackgroundColor) - + Section("settings.display.section.display") { Picker("settings.display.avatar.position", selection: $theme.avatarPosition) { ForEach(Theme.AvatarPosition.allCases, id: \.rawValue) { position in diff --git a/IceCubesApp/App/Tabs/Settings/IconSelectorView.swift b/IceCubesApp/App/Tabs/Settings/IconSelectorView.swift index 3963f7d3..77bf24fe 100644 --- a/IceCubesApp/App/Tabs/Settings/IconSelectorView.swift +++ b/IceCubesApp/App/Tabs/Settings/IconSelectorView.swift @@ -44,9 +44,9 @@ struct IconSelectorView: View { let icons: [Icon] static let items = [ - IconSelector(title:"settings.app.icon.official".localized, icons: [.primary, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8, - .alt9, .alt10, .alt11, .alt12, .alt13, .alt14, - .alt15, .alt16, .alt17, .alt18, .alt19, .alt25]), + IconSelector(title: "settings.app.icon.official".localized, icons: [.primary, .alt1, .alt2, .alt3, .alt4, .alt5, .alt6, .alt7, .alt8, + .alt9, .alt10, .alt11, .alt12, .alt13, .alt14, + .alt15, .alt16, .alt17, .alt18, .alt19, .alt25]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Albert Kinng", icons: [.alt20, .alt21, .alt22, .alt23, .alt24]), IconSelector(title: "\("settings.app.icon.designed-by".localized) Dan van Moll", icons: [.alt26, .alt27, .alt28]), IconSelector(title: "\("settings.app.icon.designed-by".localized) @te6-in (GitHub)", icons: [.alt29, .alt30, .alt31, .alt32]), @@ -108,7 +108,7 @@ struct IconSelectorView: View { } extension String { - var localized: String { - return NSLocalizedString(self, comment:"") - } + var localized: String { + return NSLocalizedString(self, comment: "") + } } diff --git a/IceCubesApp/App/Tabs/Settings/SettingsTab.swift b/IceCubesApp/App/Tabs/Settings/SettingsTab.swift index 32b87085..3a672186 100644 --- a/IceCubesApp/App/Tabs/Settings/SettingsTab.swift +++ b/IceCubesApp/App/Tabs/Settings/SettingsTab.swift @@ -100,7 +100,7 @@ struct SettingsTabs: View { } .listRowBackground(theme.primaryBackgroundColor) } - + private func logoutAccount(account: AppAccount) async { if let token = account.oauthToken, let sub = pushNotifications.subscriptions.first(where: { $0.account.token == token }) @@ -235,7 +235,7 @@ struct SettingsTabs: View { AddAccountView() } } - + private var editAccountButton: some View { Button(role: isEditingAccount ? .none : .destructive) { withAnimation { diff --git a/IceCubesNotifications/NotificationService.swift b/IceCubesNotifications/NotificationService.swift index a3ca5ab7..700357eb 100644 --- a/IceCubesNotifications/NotificationService.swift +++ b/IceCubesNotifications/NotificationService.swift @@ -1,13 +1,13 @@ import AppAccount import CryptoKit import Env +import Intents import KeychainSwift import Models -import UIKit -import UserNotifications -import Intents import Network import Notifications +import UIKit +import UserNotifications @MainActor class NotificationService: UNNotificationServiceExtension { @@ -62,13 +62,12 @@ class NotificationService: UNNotificationServiceExtension { bestAttemptContent.body = notification.body.escape() bestAttemptContent.userInfo["plaintext"] = plaintextData bestAttemptContent.sound = UNNotificationSound(named: UNNotificationSoundName(rawValue: "glass.caf")) - let preferences = UserPreferences.shared preferences.pushNotificationsCount += 1 bestAttemptContent.badge = .init(integerLiteral: preferences.pushNotificationsCount) - + if let urlString = notification.icon, let url = URL(string: urlString) { @@ -81,9 +80,10 @@ class NotificationService: UNNotificationServiceExtension { if let (data, _) = try? await URLSession.shared.data(for: .init(url: url)) { if let image = UIImage(data: data) { try? image.pngData()?.write(to: fileURL) - + if let remoteNotification = await toRemoteNotification(localNotification: notification), - let type = remoteNotification.supportedType { + let type = remoteNotification.supportedType + { let intent = buildMessageIntent(remoteNotification: remoteNotification, currentUser: bestAttemptContent.userInfo["i"] as? String ?? "", avatarURL: fileURL) @@ -111,7 +111,7 @@ class NotificationService: UNNotificationServiceExtension { } } } - + private func toRemoteNotification(localNotification: MastodonPushNotification) async -> Models.Notification? { do { if let account = AppAccountsManager.shared.availableAccounts.first(where: { $0.oauthToken?.accessToken == localNotification.accessToken }) { @@ -124,10 +124,11 @@ class NotificationService: UNNotificationServiceExtension { } return nil } - + private func buildMessageIntent(remoteNotification: Models.Notification, currentUser: String, - avatarURL: URL) -> INSendMessageIntent { + avatarURL: URL) -> INSendMessageIntent + { let handle = INPersonHandle(value: remoteNotification.account.id, type: .unknown) let avatar = INImage(url: avatarURL) let sender = INPerson(personHandle: handle, diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountViewModel.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountViewModel.swift index 6264ab55..be134894 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountViewModel.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountViewModel.swift @@ -19,6 +19,7 @@ public class AppAccountViewModel: ObservableObject { } } } + @Published var roundedAvatar: UIImage? var acct: String { @@ -39,31 +40,32 @@ public class AppAccountViewModel: ObservableObject { do { account = Self.accountsCache[appAccount.id] roundedAvatar = Self.avatarsCache[appAccount.id] - + account = try await client.get(endpoint: Accounts.verifyCredentials) Self.accountsCache[appAccount.id] = account - + if let account { await refreshAvatar(account: account) } - + } catch {} } - + private func refreshAcct(account: Account) { do { if appAccount.accountName == nil { appAccount.accountName = "\(account.acct)@\(appAccount.server)" try appAccount.save() } - } catch { } + } catch {} } - + private func refreshAvatar(account: Account) async { if let (data, _) = try? await URLSession.shared.data(from: account.avatar), - let image = UIImage(data: data)?.roundedImage { - roundedAvatar = image - Self.avatarsCache[account.id] = image + let image = UIImage(data: data)?.roundedImage + { + roundedAvatar = image + Self.avatarsCache[account.id] = image } } } diff --git a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift index 5b641211..fd5a94b9 100644 --- a/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift +++ b/Packages/AppAccount/Sources/AppAccount/AppAccountsSelectorView.swift @@ -64,7 +64,7 @@ public struct AppAccountsSelectorView: View { .frame(width: 9, height: 9) } } - .accessibilityLabel("accessibility.app-account.selector.accounts") + .accessibilityLabel("accessibility.app-account.selector.accounts") } @ViewBuilder diff --git a/Packages/Env/Sources/Env/CurrentAccount.swift b/Packages/Env/Sources/Env/CurrentAccount.swift index 935e55db..5477800b 100644 --- a/Packages/Env/Sources/Env/CurrentAccount.swift +++ b/Packages/Env/Sources/Env/CurrentAccount.swift @@ -4,8 +4,8 @@ import Network @MainActor public class CurrentAccount: ObservableObject { - static private var accountsCache: [String: Account] = [:] - + private static var accountsCache: [String: Account] = [:] + @Published public private(set) var account: Account? @Published public private(set) var lists: [List] = [] @Published public private(set) var tags: [Tag] = [] diff --git a/Packages/Env/Sources/Env/CustomEnvValues.swift b/Packages/Env/Sources/Env/CustomEnvValues.swift index d6ada5d6..fb8e177a 100644 --- a/Packages/Env/Sources/Env/CustomEnvValues.swift +++ b/Packages/Env/Sources/Env/CustomEnvValues.swift @@ -18,12 +18,12 @@ public extension EnvironmentValues { get { self[SecondaryColumnKey.self] } set { self[SecondaryColumnKey.self] = newValue } } - + var extraLeadingInset: CGFloat { get { self[ExtraLeadingInset.self] } set { self[ExtraLeadingInset.self] = newValue } } - + var isCompact: Bool { get { self[IsCompact.self] } set { self[IsCompact.self] = newValue } diff --git a/Packages/Env/Sources/Env/PushNotificationsService.swift b/Packages/Env/Sources/Env/PushNotificationsService.swift index a1401f42..091e0804 100644 --- a/Packages/Env/Sources/Env/PushNotificationsService.swift +++ b/Packages/Env/Sources/Env/PushNotificationsService.swift @@ -30,21 +30,21 @@ public class PushNotificationsService: NSObject, ObservableObject { static let keychainAuthKey = "notifications_auth_key" static let keychainPrivateKey = "notifications_private_key" } - + public static let shared = PushNotificationsService() public private(set) var subscriptions: [PushNotificationSubscriptionSettings] = [] @Published public var pushToken: Data? - + @Published public var handledNotification: HandledNotification? - + override init() { super.init() - + UNUserNotificationCenter.current().delegate = self } - + private var keychain: KeychainSwift { let keychain = KeychainSwift() #if !DEBUG && !targetEnvironment(simulator) @@ -135,18 +135,19 @@ public class PushNotificationsService: NSObject, ObservableObject { } extension PushNotificationsService: UNUserNotificationCenterDelegate { - public func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { + public func userNotificationCenter(_: UNUserNotificationCenter, didReceive response: UNNotificationResponse) async { guard let plaintext = response.notification.request.content.userInfo["plaintext"] as? Data, let mastodonPushNotification = try? JSONDecoder().decode(MastodonPushNotification.self, from: plaintext), - let account = subscriptions.first(where: { $0.account.token.accessToken == mastodonPushNotification.accessToken }) else { - return + let account = subscriptions.first(where: { $0.account.token.accessToken == mastodonPushNotification.accessToken }) + else { + return } do { let client = Client(server: account.account.server, oauthToken: account.account.token) let notification: Models.Notification = - try await client.get(endpoint: Notifications.notification(id:String(mastodonPushNotification.notificationID))) - self.handledNotification = .init(account: account.account, notification: notification) - } catch { } + try await client.get(endpoint: Notifications.notification(id: String(mastodonPushNotification.notificationID))) + handledNotification = .init(account: account.account, notification: notification) + } catch {} } } diff --git a/Packages/Env/Sources/Env/StatusAction.swift b/Packages/Env/Sources/Env/StatusAction.swift index b30c2a86..b50ac9db 100644 --- a/Packages/Env/Sources/Env/StatusAction.swift +++ b/Packages/Env/Sources/Env/StatusAction.swift @@ -42,10 +42,10 @@ public enum StatusAction: String, CaseIterable, Identifiable { } public func color(themeTintColor: Color, useThemeColor: Bool, outside: Bool) -> Color { - if (useThemeColor) { + if useThemeColor { return outside ? themeTintColor : .gray } - + switch self { case .none: return .gray diff --git a/Packages/Env/Sources/Env/UserPreferences.swift b/Packages/Env/Sources/Env/UserPreferences.swift index dc990dc6..e5247819 100644 --- a/Packages/Env/Sources/Env/UserPreferences.swift +++ b/Packages/Env/Sources/Env/UserPreferences.swift @@ -38,7 +38,7 @@ public class UserPreferences: ObservableObject { @AppStorage("show_tab_label_iphone") public var showiPhoneTabLabel = true @AppStorage("show_alt_text_for_media") public var showAltTextForMedia = true - + @AppStorage("show_second_column_ipad") public var showiPadSecondaryColumn = true @AppStorage("swipeactions-status-trailing-right") public var swipeActionsStatusTrailingRight = StatusAction.favorite @@ -47,9 +47,9 @@ public class UserPreferences: ObservableObject { @AppStorage("swipeactions-status-leading-right") public var swipeActionsStatusLeadingRight = StatusAction.none @AppStorage("swipeactions-use-theme-color") public var swipeActionsUseThemeColor = false @AppStorage("swipeactions-icon-style") public var swipeActionsIconStyle: SwipeActionsIconStyle = .iconWithText - + @AppStorage("font_use_sf_rounded") public var useSFRoundedFont = false - + @AppStorage("requested_review") public var requestedReview = false public enum SwipeActionsIconStyle: String, CaseIterable { diff --git a/Packages/Models/Sources/Models/Account.swift b/Packages/Models/Sources/Models/Account.swift index 383f631f..a435518f 100644 --- a/Packages/Models/Sources/Models/Account.swift +++ b/Packages/Models/Sources/Models/Account.swift @@ -4,7 +4,7 @@ public final class Account: Codable, Identifiable, Equatable, Hashable { public static func == (lhs: Account, rhs: Account) -> Bool { lhs.id == rhs.id } - + public func hash(into hasher: inout Hasher) { hasher.combine(id) } @@ -55,7 +55,6 @@ public final class Account: Codable, Identifiable, Equatable, Hashable { return header.lastPathComponent != "missing.png" } - public init(id: String, username: String, displayName: String, avatar: URL, header: URL, acct: String, note: HTMLString, createdAt: ServerDate, followersCount: Int, followingCount: Int, statusesCount: Int, lastStatusAt: String? = nil, fields: [Account.Field], locked: Bool, emojis: [Emoji], url: URL? = nil, source: Account.Source? = nil, bot: Bool, discoverable: Bool? = nil) { self.id = id self.username = username @@ -77,7 +76,7 @@ public final class Account: Codable, Identifiable, Equatable, Hashable { self.bot = bot self.discoverable = discoverable } - + public static func placeholder() -> Account { .init(id: UUID().uuidString, username: "Username", diff --git a/Packages/Models/Sources/Models/Relationship.swift b/Packages/Models/Sources/Models/Relationship.swift index 09965d5c..e1c8aa58 100644 --- a/Packages/Models/Sources/Models/Relationship.swift +++ b/Packages/Models/Sources/Models/Relationship.swift @@ -31,7 +31,7 @@ public struct Relationship: Codable { notifying: false) } } - + public extension Relationship { init(from decoder: Decoder) throws { let values = try decoder.container(keyedBy: CodingKeys.self) diff --git a/Packages/Network/Sources/Network/String.swift b/Packages/Network/Sources/Network/String.swift index 898c089c..4c72e2e0 100644 --- a/Packages/Network/Sources/Network/String.swift +++ b/Packages/Network/Sources/Network/String.swift @@ -1,7 +1,7 @@ import Foundation -extension String { - public func escape() -> String { +public extension String { + func escape() -> String { return replacingOccurrences(of: "&", with: "&") .replacingOccurrences(of: "<", with: "<") .replacingOccurrences(of: ">", with: ">") @@ -10,7 +10,7 @@ extension String { .replacingOccurrences(of: "'", with: "’") } - public func URLSafeBase64ToBase64() -> String { + func URLSafeBase64ToBase64() -> String { var base64 = replacingOccurrences(of: "-", with: "+").replacingOccurrences(of: "_", with: "/") let countMod4 = count % 4 diff --git a/Packages/Notifications/Sources/Notifications/Notification+Consolidated.swift b/Packages/Notifications/Sources/Notifications/Notification+Consolidated.swift index c0208e42..c8f60477 100644 --- a/Packages/Notifications/Sources/Notifications/Notification+Consolidated.swift +++ b/Packages/Notifications/Sources/Notifications/Notification+Consolidated.swift @@ -5,32 +5,32 @@ // Created by Jérôme Danthinne on 31/01/2023. // -import Models import Foundation +import Models extension Array where Element == Models.Notification { func consolidated(selectedType: Models.Notification.NotificationType?) async -> [ConsolidatedNotification] { - await withCheckedContinuation({ result in + await withCheckedContinuation { result in DispatchQueue.global().async { let notifications: [ConsolidatedNotification] = - Dictionary(grouping: self) { $0.consolidationId(selectedType: selectedType) } - .values - .compactMap { notifications in - guard let notification = notifications.first, - let supportedType = notification.supportedType - else { return nil } + Dictionary(grouping: self) { $0.consolidationId(selectedType: selectedType) } + .values + .compactMap { notifications in + guard let notification = notifications.first, + let supportedType = notification.supportedType + else { return nil } - return ConsolidatedNotification(notifications: notifications, - type: supportedType, - createdAt: notification.createdAt, - accounts: notifications.map(\.account), - status: notification.status) - } - .sorted { - $0.createdAt.asDate > $1.createdAt.asDate - } + return ConsolidatedNotification(notifications: notifications, + type: supportedType, + createdAt: notification.createdAt, + accounts: notifications.map(\.account), + status: notification.status) + } + .sorted { + $0.createdAt.asDate > $1.createdAt.asDate + } result.resume(returning: notifications) } - }) + } } } diff --git a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift index 2fba65f6..019aa879 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationRowView.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationRowView.swift @@ -2,9 +2,9 @@ import DesignSystem import EmojiText import Env import Models +import Network import Status import SwiftUI -import Network struct NotificationRowView: View { @EnvironmentObject private var theme: Theme @@ -28,7 +28,8 @@ struct NotificationRowView: View { makeMainLabel(type: notification.type) makeContent(type: notification.type) if notification.type == .follow_request, - followRequests.map(\.id).contains(notification.accounts[0].id) { + followRequests.map(\.id).contains(notification.accounts[0].id) + { FollowRequestButtons(account: notification.accounts[0]) } } diff --git a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift index c44843ec..2b181349 100644 --- a/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift +++ b/Packages/Notifications/Sources/Notifications/NotificationTypeExt.swift @@ -23,7 +23,7 @@ extension Models.Notification.NotificationType { return "notifications.label.update" } } - + public func notificationKey() -> String { switch self { case .status: diff --git a/Packages/Status/Sources/Status/Detail/StatusDetailView.swift b/Packages/Status/Sources/Status/Detail/StatusDetailView.swift index a0c30be4..ec881f6e 100644 --- a/Packages/Status/Sources/Status/Detail/StatusDetailView.swift +++ b/Packages/Status/Sources/Status/Detail/StatusDetailView.swift @@ -93,13 +93,14 @@ public struct StatusDetailView: View { .navigationTitle(viewModel.title) .navigationBarTitleDisplayMode(.inline) } - - private func makeStatusesListView(statuses: [Status], date: Date) -> some View { + + private func makeStatusesListView(statuses: [Status], date _: Date) -> some View { ForEach(statuses) { status in var isReplyToPrevious: Bool = false if let index = statuses.firstIndex(where: { $0.id == status.id }), index > 0, - statuses[index - 1].id == status.inReplyToId { + statuses[index - 1].id == status.inReplyToId + { isReplyToPrevious = true } let viewModel: StatusRowViewModel = .init(status: status, diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorMediaView.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorMediaView.swift index 488c8cf1..f03ec15b 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorMediaView.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorMediaView.swift @@ -5,7 +5,7 @@ import Models import NukeUI import SwiftUI -struct StatusEditorMediaView: View { +struct StatusEditorMediaView: View { @EnvironmentObject private var theme: Theme @EnvironmentObject private var currentInstance: CurrentInstance @ObservedObject var viewModel: StatusEditorViewModel diff --git a/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift b/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift index c453aed3..524fb8e5 100644 --- a/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift +++ b/Packages/Status/Sources/Status/Editor/Components/StatusEditorUTTypeSupported.swift @@ -21,7 +21,7 @@ enum StatusEditorUTTypeSupported: String, CaseIterable { case gif = "public.gif" case gif2 = "com.compuserve.gif" case quickTimeMovie = "com.apple.quicktime-movie" - + case uiimage = "com.apple.uikit.image" static func types() -> [UTType] { @@ -57,8 +57,8 @@ enum StatusEditorUTTypeSupported: String, CaseIterable { if let image = result as? UIImage { return image } else if let imageURL = result as? URL, - let data = try? Data(contentsOf: imageURL), - let image = UIImage(data: data) + let data = try? Data(contentsOf: imageURL), + let image = UIImage(data: data) { return image } else if let data = result as? Data, diff --git a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift index c8206fda..fc7caf0e 100644 --- a/Packages/Status/Sources/Status/Editor/StatusEditorView.swift +++ b/Packages/Status/Sources/Status/Editor/StatusEditorView.swift @@ -7,9 +7,9 @@ import Models import Network import NukeUI import PhotosUI +import StoreKit import SwiftUI import UIKit -import StoreKit public struct StatusEditorView: View { @EnvironmentObject private var appAccounts: AppAccountsManager @@ -204,8 +204,8 @@ public struct StatusEditorView: View { object: nil) if !viewModel.mode.isInShareExtension && !preferences.requestedReview { if let scene = UIApplication.shared.connectedScenes.first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene { - SKStoreReviewController.requestReview(in: scene) - } + SKStoreReviewController.requestReview(in: scene) + } preferences.requestedReview = true } } diff --git a/Packages/Status/Sources/Status/Embed/StatusEmbededView.swift b/Packages/Status/Sources/Status/Embed/StatusEmbededView.swift index 4dfe08b3..678ffc09 100644 --- a/Packages/Status/Sources/Status/Embed/StatusEmbededView.swift +++ b/Packages/Status/Sources/Status/Embed/StatusEmbededView.swift @@ -1,9 +1,9 @@ import DesignSystem import EmojiText -import Models -import SwiftUI import Env +import Models import Network +import SwiftUI @MainActor public struct StatusEmbeddedView: View { @@ -27,7 +27,7 @@ public struct StatusEmbeddedView: View { client: client, routerPath: routerPath, showActions: false)) - .environment(\.isCompact, true) + .environment(\.isCompact, true) } Spacer() } diff --git a/Packages/Status/Sources/Status/List/StatusesListView.swift b/Packages/Status/Sources/Status/List/StatusesListView.swift index dc45f9f3..41936baa 100644 --- a/Packages/Status/Sources/Status/List/StatusesListView.swift +++ b/Packages/Status/Sources/Status/List/StatusesListView.swift @@ -1,9 +1,9 @@ import DesignSystem import Env import Models +import Network import Shimmer import SwiftUI -import Network public struct StatusesListView: View where Fetcher: StatusesFetcher { @EnvironmentObject private var theme: Theme diff --git a/Packages/Status/Sources/Status/Row/StatusRowView.swift b/Packages/Status/Sources/Status/Row/StatusRowView.swift index 706a45e6..9aa5098f 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowView.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowView.swift @@ -11,7 +11,7 @@ public struct StatusRowView: View { @Environment(\.isCompact) private var isCompact: Bool @EnvironmentObject private var theme: Theme - + @StateObject var viewModel: StatusRowViewModel public init(viewModel: StatusRowViewModel) { @@ -41,7 +41,8 @@ public struct StatusRowView: View { } HStack(alignment: .top, spacing: .statusColumnsSpacing) { if !isCompact, - theme.avatarPosition == .leading { + theme.avatarPosition == .leading + { Button { viewModel.routerPath.navigate(to: .accountDetailWithAccount(account: status.account)) } label: { @@ -180,7 +181,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 c9afa2f3..ca7660c7 100644 --- a/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift +++ b/Packages/Status/Sources/Status/Row/StatusRowViewModel.swift @@ -12,7 +12,7 @@ public class StatusRowViewModel: ObservableObject { let isFocused: Bool let isRemote: Bool let showActions: Bool - + @Published var favoritesCount: Int @Published var isFavorited: Bool @Published var isReblogged: Bool @@ -31,7 +31,7 @@ public class StatusRowViewModel: ObservableObject { @Published var favoriters: [Account] = [] @Published var rebloggers: [Account] = [] - + @Published var isLoadingRemoteContent: Bool = false @Published var localStatusId: String? @Published var localStatus: Status? @@ -334,7 +334,7 @@ public class StatusRowViewModel: ObservableObject { } } } - + func fetchRemoteStatus() async -> Bool { guard isRemote, let remoteStatusURL = URL(string: status.reblog?.url ?? status.url ?? "") else { return false } isLoadingRemoteContent = true @@ -344,8 +344,8 @@ public class StatusRowViewModel: ObservableObject { following: nil), forceVersion: .v2) if let status = results?.statuses.first { - self.localStatusId = status.id - self.localStatus = status + localStatusId = status.id + localStatus = status isLoadingRemoteContent = false return true } else { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift index 9631bf82..afe3d3ad 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowActionsView.swift @@ -63,7 +63,8 @@ struct StatusRowActionsView: View { ForEach(Actions.allCases, id: \.self) { action in if action == .share { if let urlString = viewModel.status.reblog?.url ?? viewModel.status.url, - let url = URL(string: urlString) { + let url = URL(string: urlString) + { 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)) { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContentView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContentView.swift index 88a752a5..e8dbc79d 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContentView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContentView.swift @@ -1,17 +1,17 @@ -import SwiftUI import DesignSystem -import Models import Env +import Models +import SwiftUI struct StatusRowContentView: View { @Environment(\.redactionReasons) private var reasons @Environment(\.isCompact) private var isCompact - + @EnvironmentObject private var theme: Theme - + let status: AnyStatus @ObservedObject var viewModel: StatusRowViewModel - + var body: some View { if !status.spoilerText.asRawText.isEmpty { StatusRowSpoilerView(status: status, displaySpoiler: $viewModel.displaySpoiler) @@ -26,7 +26,8 @@ struct StatusRowContentView: View { if !reasons.contains(.placeholder), !isCompact, - (viewModel.isEmbedLoading || viewModel.embeddedStatus != nil) { + viewModel.isEmbedLoading || viewModel.embeddedStatus != nil + { StatusEmbeddedView(status: viewModel.embeddedStatus ?? Status.placeholder(), client: viewModel.client, routerPath: viewModel.routerPath) @@ -35,7 +36,7 @@ struct StatusRowContentView: View { .shimmering(active: viewModel.isEmbedLoading) .transition(.opacity) } - + if !status.mediaAttachments.isEmpty { HStack { StatusRowMediaPreviewView(attachments: status.mediaAttachments, @@ -47,7 +48,7 @@ struct StatusRowContentView: View { } .padding(.vertical, 4) } - + if let card = status.card, !viewModel.isEmbedLoading, !isCompact, diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift index a43b1922..298a7e24 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowContextMenu.swift @@ -57,7 +57,8 @@ struct StatusRowContextMenu: View { Divider() if let urlString = viewModel.status.reblog?.url ?? viewModel.status.url, - let url = URL(string: urlString) { + let url = URL(string: urlString) + { 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)) { diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift index 79db95be..974b0b0c 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowHeaderView.swift @@ -1,13 +1,13 @@ -import SwiftUI import DesignSystem import Models +import SwiftUI struct StatusRowHeaderView: View { @EnvironmentObject private var theme: Theme - + let status: AnyStatus let viewModel: StatusRowViewModel - + var body: some View { HStack(alignment: .center) { Button { @@ -23,7 +23,7 @@ struct StatusRowHeaderView: View { .accessibilityElement() .accessibilityLabel(Text("\(status.account.displayName)")) } - + @ViewBuilder private func accountView(status: AnyStatus) -> some View { HStack(alignment: .center) { @@ -46,7 +46,7 @@ struct StatusRowHeaderView: View { } } } - + @ViewBuilder private var threadIcon: some View { if viewModel.status.reblog?.inReplyToAccountId != nil || viewModel.status.inReplyToAccountId != nil { @@ -57,7 +57,7 @@ struct StatusRowHeaderView: View { .foregroundColor(.gray) } } - + private var contextMenuButton: some View { Menu { StatusRowContextMenu(viewModel: viewModel) diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift index f83d830d..98c0e7dd 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReblogView.swift @@ -1,9 +1,9 @@ -import SwiftUI import DesignSystem +import SwiftUI struct StatusRowReblogView: View { let viewModel: StatusRowViewModel - + var body: some View { if viewModel.status.reblog != nil { HStack(spacing: 2) { @@ -27,4 +27,3 @@ struct StatusRowReblogView: View { } } } - diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReplyView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReplyView.swift index fa5ac8bb..f1081281 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowReplyView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowReplyView.swift @@ -1,9 +1,9 @@ -import SwiftUI import DesignSystem +import SwiftUI struct StatusRowReplyView: View { let viewModel: StatusRowViewModel - + var body: some View { if let accountId = viewModel.status.inReplyToAccountId, let mention = viewModel.status.mentions.first(where: { $0.id == accountId }) diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSpoilerView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSpoilerView.swift index 4ef3ea28..15c68092 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSpoilerView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSpoilerView.swift @@ -1,11 +1,11 @@ -import SwiftUI import DesignSystem import Models +import SwiftUI struct StatusRowSpoilerView: View { let status: AnyStatus @Binding var displaySpoiler: Bool - + var body: some View { HStack(alignment: .top) { Text("⚠︎") diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift index 8f54a2f7..4105a121 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowSwipeView.swift @@ -1,19 +1,19 @@ -import SwiftUI +import DesignSystem import Env import Models -import DesignSystem +import SwiftUI struct StatusRowSwipeView: View { @EnvironmentObject private var theme: Theme @EnvironmentObject private var preferences: UserPreferences - + enum Mode { case leading, trailing } - + let viewModel: StatusRowViewModel let mode: Mode - + var body: some View { switch mode { case .leading: @@ -22,7 +22,7 @@ struct StatusRowSwipeView: View { trailingSwipeActions } } - + @ViewBuilder private var trailingSwipeActions: some View { if preferences.swipeActionsStatusTrailingRight != StatusAction.none, !viewModel.isRemote { @@ -105,10 +105,10 @@ struct StatusRowSwipeView: View { makeSwipeLabel(action: action, style: preferences.swipeActionsIconStyle) } } - + @ViewBuilder private func makeSwipeLabel(action: StatusAction, style: UserPreferences.SwipeActionsIconStyle) -> some View { - switch (style) { + switch style { case .iconOnly: Label(action.displayName(isReblogged: viewModel.isReblogged, isFavorited: viewModel.isFavorited, isBookmarked: viewModel.isBookmarked), systemImage: action.iconName(isReblogged: viewModel.isReblogged, isFavorited: viewModel.isFavorited, isBookmarked: viewModel.isBookmarked)) .labelStyle(.iconOnly) diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift index 1d04b381..42d87d44 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTextView.swift @@ -1,11 +1,11 @@ -import SwiftUI import DesignSystem import Models +import SwiftUI struct StatusRowTextView: View { let status: AnyStatus let viewModel: StatusRowViewModel - + var body: some View { HStack { EmojiTextApp(status.content, emojis: status.emojis, language: status.language) diff --git a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTranslateView.swift b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTranslateView.swift index f25614d9..4eef391c 100644 --- a/Packages/Status/Sources/Status/Row/Subviews/StatusRowTranslateView.swift +++ b/Packages/Status/Sources/Status/Row/Subviews/StatusRowTranslateView.swift @@ -1,14 +1,14 @@ -import SwiftUI -import Models import DesignSystem import Env +import Models +import SwiftUI struct StatusRowTranslateView: View { @EnvironmentObject private var preferences: UserPreferences - + let status: AnyStatus @ObservedObject var viewModel: StatusRowViewModel - + private var shouldShowTranslateButton: Bool { let statusLang = viewModel.getStatusLang() @@ -22,10 +22,10 @@ struct StatusRowTranslateView: View { return false } } - + var body: some View { if let userLang = preferences.serverPreferences?.postLanguage, - shouldShowTranslateButton + shouldShowTranslateButton { Button { Task { diff --git a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift index 21769fc2..099f8a9b 100644 --- a/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift +++ b/Packages/Timeline/Sources/Timeline/TimelineViewModel.swift @@ -248,7 +248,7 @@ extension TimelineViewModel: StatusesFetcher { canStreamEvents = true return } - + // As this is a long runnign task we need to ensure that the user didn't changed the timeline filter. guard initialTimeline == timeline else { canStreamEvents = true