SwiftFormat

This commit is contained in:
Thomas Ricouard 2023-03-13 13:38:28 +01:00
parent f1267620be
commit 6c307aba63
58 changed files with 313 additions and 299 deletions

View file

@ -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 {

View file

@ -112,7 +112,8 @@ struct IceCubesApp: App {
SideBarView(selectedTab: $selectedTab,
popToRootTab: $popToRootTab,
tabs: availableTabs,
routerPath: sidebarRouterPath) {
routerPath: sidebarRouterPath)
{
GeometryReader { _ in
HStack(spacing: 0) {
ZStack {

View file

@ -30,7 +30,6 @@ struct AddAccountView: View {
private let instanceNamePublisher = PassthroughSubject<String, Never>()
private var sanitizedName: String {
get {
var name = instanceName
.replacingOccurrences(of: "http://", with: "")
.replacingOccurrences(of: "https://", with: "")
@ -41,7 +40,6 @@ struct AddAccountView: View {
}
return name
}
}
@FocusState private var isInstanceURLFieldFocused: Bool
@ -94,7 +92,7 @@ struct AddAccountView: View {
.onChange(of: instanceName) { newValue in
instanceNamePublisher.send(newValue)
}
.onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { newValue in
.onReceive(instanceNamePublisher.debounce(for: .milliseconds(500), scheduler: DispatchQueue.main)) { _ in
// let newValue = newValue
// .replacingOccurrences(of: "http://", with: "")
// .replacingOccurrences(of: "https://", with: "")

View file

@ -1,10 +1,10 @@
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

View file

@ -179,7 +179,6 @@ struct SupportAppView: View {
Spacer()
makePurchaseButton(product: subscription)
}
}
.padding(.vertical, 8)
}

View file

@ -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

View file

@ -54,7 +54,8 @@ class ShareViewController: UIViewController {
NotificationCenter.default.addObserver(forName: NotificationsName.shareSheetClose,
object: nil,
queue: nil) { _ in
queue: nil)
{ _ in
self.close()
}
}

View file

@ -1,6 +1,6 @@
import SwiftUI
import Env
import Network
import SwiftUI
public struct AccountDetailContextMenu: View {
@EnvironmentObject private var client: Client

View file

@ -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)
}

View file

@ -98,6 +98,5 @@ public struct AccountsListRow: View {
.environmentObject(currentAccount)
.environmentObject(client)
}
}
}

View file

@ -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:
@ -96,8 +96,7 @@ struct EditFilterView: View {
if expirySelection != .infinite {
DatePicker("filter.edit.expiry.date-time",
selection: Binding<Date>(get: { self.expiresAt ?? Date() }, set: { self.expiresAt = $0 }),
displayedComponents: [.date, .hourAndMinute]
)
displayedComponents: [.date, .hourAndMinute])
.disabled(expirySelection != .custom)
}
}

View file

@ -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()

View file

@ -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()

View file

@ -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()
}

View file

@ -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
}
}

View file

@ -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)
}
}
}

View file

@ -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) {

View file

@ -1,6 +1,6 @@
import AVKit
import CoreHaptics
import UIKit
import AVKit
public class SoundEffectManager {
public static let shared: SoundEffectManager = .init()

View file

@ -1,7 +1,7 @@
import Foundation
import SwiftUI
import Models
import Network
import SwiftUI
@MainActor
public protocol StatusDataControlling: ObservableObject {
@ -65,23 +65,23 @@ public final class StatusDataController: StatusDataControlling {
self.status = status
self.client = client
self.isReblogged = status.reblogged == true
self.isBookmarked = status.bookmarked == true
self.isFavorited = status.favourited == true
isReblogged = status.reblogged == true
isBookmarked = status.bookmarked == true
isFavorited = status.favourited == true
self.reblogsCount = status.reblogsCount
self.repliesCount = status.repliesCount
self.favoritesCount = status.favouritesCount
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
isReblogged = status.reblogged == true
isBookmarked = status.bookmarked == true
isFavorited = status.favourited == true
self.reblogsCount = status.reblogsCount
self.repliesCount = status.repliesCount
self.favoritesCount = status.favouritesCount
reblogsCount = status.reblogsCount
repliesCount = status.repliesCount
favoritesCount = status.favouritesCount
if publishUpdate {
objectWillChange.send()
@ -105,7 +105,6 @@ public final class StatusDataController: StatusDataControlling {
}
}
public func toggleReblog(remoteStatus: String?) async {
guard client.isAuth else { return }
isReblogged.toggle()

View file

@ -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]
}
}

View file

@ -127,7 +127,8 @@ 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
.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)
@ -144,7 +145,8 @@ 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
.prefix(upTo: viewModel.trendingTags.count > 5 ? 5 : viewModel.trendingTags.count))
{ tag in
TagRowView(tag: tag)
.listRowBackground(theme.primaryBackgroundColor)
.padding(.vertical, 4)
@ -160,7 +162,8 @@ 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
.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)
@ -177,7 +180,8 @@ 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
.prefix(upTo: viewModel.trendingLinks.count > 3 ? 3 : viewModel.trendingLinks.count))
{ card in
StatusRowCardView(card: card)
.listRowBackground(theme.primaryBackgroundColor)
.padding(.vertical, 8)

View file

@ -1,6 +1,6 @@
import SwiftUI
import Models
import DesignSystem
import Models
import SwiftUI
public struct TagsListView: View {
@EnvironmentObject private var theme: Theme

View file

@ -2,6 +2,7 @@ import Foundation
public struct ServerError: Decodable, Error {
public let error: String?
public var httpCode: Int
}
extension ServerError: Sendable {}

View file

@ -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 {}

View file

@ -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<Entity: Decodable>(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

View file

@ -47,7 +47,7 @@ public struct OpenAIClient {
}
public init(content: String, temperature: CGFloat) {
self.messages = [.init(content: content)]
messages = [.init(content: content)]
self.temperature = temperature
}
}

View file

@ -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()
}

View file

@ -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()
}

View file

@ -1,8 +1,8 @@
import Env
import Foundation
import Models
import Network
import SwiftUI
import Env
@MainActor
class StatusDetailViewModel: ObservableObject {

View file

@ -51,7 +51,8 @@ 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)
}
@ -59,7 +60,6 @@ struct StatusEditorAccessoryView: View {
.accessibilityLabel("accessibility.editor.button.attach-photo")
.disabled(viewModel.showPoll)
Button {
withAnimation {
viewModel.showPoll.toggle()

View file

@ -1,6 +1,6 @@
import AVFoundation
import Foundation
import UIKit
import AVFoundation
actor StatusEditorCompressor {
enum CompressorError: Error {
@ -45,7 +45,7 @@ actor StatusEditorCompressor {
}()
let destinationProperties = [
kCGImageDestinationLossyCompressionQuality: isPNG ? 1.0 : 0.75
kCGImageDestinationLossyCompressionQuality: isPNG ? 1.0 : 0.75,
] as CFDictionary
CGImageDestinationAddImage(imageDestination, cgImage, destinationProperties)
@ -66,12 +66,13 @@ actor StatusEditorCompressor {
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
@ -97,5 +98,4 @@ actor StatusEditorCompressor {
}
}
}
}

View file

@ -31,7 +31,7 @@ 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]
}

View file

@ -20,6 +20,7 @@ public class StatusEditorViewModel: NSObject, ObservableObject {
}
}
}
var theme: Theme?
var preferences: UserPreferences?
var languageConfirmationDialogLanguages: (detected: String, selected: String)?
@ -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,

View file

@ -16,7 +16,8 @@ public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
public init(fetcher: Fetcher,
client: Client,
routerPath: RouterPath,
isRemote: Bool = false) {
isRemote: Bool = false)
{
self.fetcher = fetcher
self.isRemote = isRemote
self.client = client
@ -33,7 +34,8 @@ public struct StatusesListView<Fetcher>: 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()
}

View file

@ -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()

View file

@ -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,6 +39,7 @@ 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
@ -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,7 +113,6 @@ public class StatusRowViewModel: ObservableObject {
displaySpoiler = !finalStatus.spoilerText.asRawText.isEmpty
}
if status.mentions.first(where: { $0.id == CurrentAccount.shared.account?.id }) != nil {
userMentionned = true
} else {
@ -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
@ -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 {

View file

@ -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)
@ -151,7 +153,6 @@ struct StatusRowActionsView: View {
}
}
private func handleAction(action: Action) {
Task {
if viewModel.isRemote, viewModel.localStatusId == nil || viewModel.localStatus == nil {

View file

@ -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")
}

View file

@ -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 ?? "")

View file

@ -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 {}
}