Swiftformat

This commit is contained in:
Thomas Ricouard 2023-02-01 12:49:59 +01:00
parent 383eb84e98
commit 4e77669181
9 changed files with 52 additions and 51 deletions

View File

@ -246,8 +246,8 @@ class AccountDetailViewModel: ObservableObject, StatusesFetcher {
}
}
}
func statusDidAppear(status: Models.Status) { }
func statusDidDisappear(status: Status) { }
func statusDidAppear(status _: Models.Status) {}
func statusDidDisappear(status _: Status) {}
}

View File

@ -36,7 +36,7 @@ public struct HTMLString: Decodable, Equatable, Hashable {
if let regex = try? NSRegularExpression(pattern: "(<span class=\"ellipsis\">(.*?)</span>)", options: .caseInsensitive) {
htmlValue = regex.stringByReplacingMatches(in: htmlValue, options: [], range: NSRange(location: 0, length: htmlValue.count), withTemplate: "$2…")
}
do {
asMarkdown = try HTMLParser().parse(html: htmlValue)
.toMarkdown()

View File

@ -17,11 +17,11 @@ public class Client: ObservableObject, Equatable, Identifiable, Hashable {
case missingApp
case invalidRedirectURL
}
public var id: String {
"\(isAuth)\(server)\(oauthToken?.accessToken ?? "")"
}
public func hash(into hasher: inout Hasher) {
hasher.combine(id)
}

View File

@ -201,7 +201,7 @@ public class StatusEditorViewModel: ObservableObject {
mentionString += "@\(mention.acct)"
}
if !mentionString.isEmpty {
mentionString += " "
mentionString += " "
}
replyToStatus = status
visibility = status.visibility

View File

@ -5,7 +5,7 @@ import SwiftUI
public struct StatusesListView<Fetcher>: View where Fetcher: StatusesFetcher {
@EnvironmentObject private var theme: Theme
@ObservedObject private var fetcher: Fetcher
private let isRemote: Bool
private let isEmbdedInList: Bool

View File

@ -1,29 +1,29 @@
import Foundation
import SwiftUI
import Models
import SwiftUI
@MainActor
class PendingStatusesObserver: ObservableObject {
let feedbackGenerator = UIImpactFeedbackGenerator(style: .light)
@Published var pendingStatusesCount: Int = 0
var disableUpdate: Bool = false
var pendingStatuses: [String] = [] {
didSet {
pendingStatusesCount = pendingStatuses.count
}
}
func removeStatus(status: Status) {
if !disableUpdate, let index = pendingStatuses.firstIndex(of: status.id) {
pendingStatuses.removeSubrange(index...(pendingStatuses.count - 1))
pendingStatuses.removeSubrange(index ... (pendingStatuses.count - 1))
feedbackGenerator.impactOccurred()
}
}
init() { }
init() {}
}
struct PendingStatusesObserverView: View {
@ -32,7 +32,7 @@ struct PendingStatusesObserverView: View {
if observer.pendingStatusesCount > 0 {
HStack(spacing: 6) {
Spacer()
Button { } label: {
Button {} label: {
Text("\(observer.pendingStatusesCount)")
}
.buttonStyle(.bordered)

View File

@ -1,18 +1,18 @@
import SwiftUI
import Models
import Network
import SwiftUI
actor TimelineCache {
static let shared: TimelineCache = .init()
private var memoryCache: [Client: [Status]] = [:]
private init() {}
func set(statuses: [Status], client: Client) {
memoryCache[client] = statuses.prefix(upTo: min(100, (statuses.count - 1))).map{ $0 }
memoryCache[client] = statuses.prefix(upTo: min(100, statuses.count - 1)).map { $0 }
}
func getStatuses(for client: Client) -> [Status]? {
memoryCache[client]
}

View File

@ -19,9 +19,9 @@ public struct TimelineView: View {
@EnvironmentObject private var routerPath: RouterPath
@StateObject private var viewModel = TimelineViewModel()
@State private var wasBackgrounded: Bool = false
@Binding var timeline: TimelineFilter
@Binding var scrollToTopSignal: Int
@ -111,7 +111,7 @@ public struct TimelineView: View {
}
case .background:
wasBackgrounded = true
default:
break
}
@ -154,9 +154,9 @@ public struct TimelineView: View {
trailing: .layoutPadding))
}
}
private var scrollToTopView: some View {
HStack{ EmptyView() }
HStack { EmptyView() }
.listRowBackground(theme.primaryBackgroundColor)
.listRowSeparator(.hidden)
.listRowInsets(.init())

View File

@ -18,14 +18,14 @@ class TimelineViewModel: ObservableObject {
private var statuses: [Status] = []
private var visibileStatusesIds = Set<String>()
var scrollToTopVisible: Bool = false
private var canStreamEvents: Bool = true
let pendingStatusesObserver: PendingStatusesObserver = .init()
let cache: TimelineCache = .shared
@Published var scrollToStatus: String?
@Published var statusesState: StatusesState = .loading
@Published var timeline: TimelineFilter = .federated {
didSet {
@ -57,7 +57,6 @@ class TimelineViewModel: ObservableObject {
client?.server ?? "Error"
}
func fetchTag(id: String) async {
guard let client else { return }
do {
@ -65,7 +64,7 @@ class TimelineViewModel: ObservableObject {
} catch {}
}
func handleEvent(event: any StreamEvent, currentAccount: CurrentAccount) {
func handleEvent(event: any StreamEvent, currentAccount _: CurrentAccount) {
if let event = event as? StreamEventUpdate,
canStreamEvents,
pendingStatusesEnabled,
@ -91,13 +90,14 @@ class TimelineViewModel: ObservableObject {
}
// MARK: - Cache
extension TimelineViewModel {
private func cache(statuses: [Status]) async {
if let client {
await cache.set(statuses: statuses, client: client)
}
}
private func getCachedStatuses() async -> [Status]? {
if let client {
return await cache.getStatuses(for: client)
@ -107,6 +107,7 @@ extension TimelineViewModel {
}
// MARK: - StatusesFetcher
extension TimelineViewModel: StatusesFetcher {
func fetchStatuses() async {
guard let client else { return }
@ -122,12 +123,12 @@ extension TimelineViewModel: StatusesFetcher {
print("timeline parse error: \(error)")
}
}
// Hydrate statuses in the Timeline when statuses are empty.
private func fetchFirstPage(client: Client) async throws {
pendingStatusesObserver.pendingStatuses = []
statusesState = .loading
// If we get statuses from the cache for the home timeline, we displays those.
// Else we fetch top most page from the API.
if let cachedStatuses = await getCachedStatuses(), timeline == .home {
@ -150,34 +151,34 @@ extension TimelineViewModel: StatusesFetcher {
}
}
}
// Fetch pages from the top most status of the tomeline.
private func fetchNewPagesFrom(latestStatus: Status, client: Client) async throws {
private func fetchNewPagesFrom(latestStatus: Status, client _: Client) async throws {
canStreamEvents = false
var newStatuses: [Status] = await fetchNewPages(minId: latestStatus.id, maxPages: 10)
// Dedup statuses, a status with the same id could have been streamed in.
newStatuses = newStatuses.filter { status in
!statuses.contains(where: { $0.id == status.id })
}
// If no new statuses, resume streaming and exit.
guard !newStatuses.isEmpty else {
canStreamEvents = true
return
}
// Keep track of the top most status, so we can scroll back to it after view update.
let topStatusId = statuses.first?.id
// Insert new statuses in internal datasource.
statuses.insert(contentsOf: newStatuses, at: 0)
// Cache statuses for home timeline.
if timeline == .home {
await cache(statuses: statuses)
}
// If pending statuses are not enabled, we simply load status on the top regardless of the current position.
if !pendingStatusesEnabled {
pendingStatusesObserver.pendingStatuses = []
@ -187,9 +188,9 @@ extension TimelineViewModel: StatusesFetcher {
}
} else {
// Append new statuses in the timeline indicator.
pendingStatusesObserver.pendingStatuses.insert(contentsOf: newStatuses.map{ $0.id }, at: 0)
pendingStatusesObserver.pendingStatuses.insert(contentsOf: newStatuses.map { $0.id }, at: 0)
pendingStatusesObserver.feedbackGenerator.impactOccurred()
// High chance the user is scrolled to the top.
// We need to update the statuses state, and then scroll to the previous top most status.
if let topStatusId, visibileStatusesIds.contains(topStatusId), scrollToTopVisible {
@ -209,7 +210,7 @@ extension TimelineViewModel: StatusesFetcher {
}
}
}
private func fetchNewPages(minId: String, maxPages: Int) async -> [Status] {
guard let client else { return [] }
var pagesLoaded = 0
@ -232,7 +233,7 @@ extension TimelineViewModel: StatusesFetcher {
}
return allStatuses
}
func fetchNextPage() async {
guard let client else { return }
do {
@ -248,12 +249,12 @@ extension TimelineViewModel: StatusesFetcher {
statusesState = .error(error: error)
}
}
func statusDidAppear(status: Status) {
pendingStatusesObserver.removeStatus(status: status)
visibileStatusesIds.insert(status.id)
}
func statusDidDisappear(status: Status) {
visibileStatusesIds.remove(status.id)
}