Checkpoint

This commit is contained in:
Thomas Ricouard 2023-09-17 07:31:25 +02:00
parent d797dc6aa9
commit ce940e063c
13 changed files with 48 additions and 60 deletions

View file

@ -3,6 +3,7 @@ import NukeUI
import Shimmer
import SwiftUI
@MainActor
public struct AvatarView: View {
@Environment(\.redactionReasons) private var reasons
@EnvironmentObject private var theme: Theme

View file

@ -2,9 +2,10 @@ import Foundation
import Models
import Network
import SwiftUI
import Observation
@MainActor
public protocol StatusDataControlling: ObservableObject {
public protocol StatusDataControlling {
var isReblogged: Bool { get set }
var isBookmarked: Bool { get set }
var isFavorited: Bool { get set }
@ -43,13 +44,13 @@ public final class StatusDataControllerProvider {
for status in statuses {
let realStatus: AnyStatus = status.reblog ?? status
let controller = dataController(for: realStatus, client: client)
controller.updateFrom(status: realStatus, publishUpdate: false)
controller.updateFrom(status: realStatus)
}
}
}
@MainActor
public final class StatusDataController: StatusDataControlling {
@Observable public final class StatusDataController: StatusDataControlling {
private let status: AnyStatus
private let client: Client
@ -74,7 +75,7 @@ public final class StatusDataController: StatusDataControlling {
favoritesCount = status.favouritesCount
}
public func updateFrom(status: AnyStatus, publishUpdate: Bool) {
public func updateFrom(status: AnyStatus) {
isReblogged = status.reblogged == true
isBookmarked = status.bookmarked == true
isFavorited = status.favourited == true
@ -82,10 +83,6 @@ public final class StatusDataController: StatusDataControlling {
reblogsCount = status.reblogsCount
repliesCount = status.repliesCount
favoritesCount = status.favouritesCount
if publishUpdate {
objectWillChange.send()
}
}
public func toggleFavorite(remoteStatus: String?) async {
@ -94,14 +91,12 @@ public final class StatusDataController: StatusDataControlling {
let id = remoteStatus ?? status.id
let endpoint = isFavorited ? Statuses.favorite(id: id) : Statuses.unfavorite(id: id)
favoritesCount += isFavorited ? 1 : -1
objectWillChange.send()
do {
let status: Status = try await client.post(endpoint: endpoint)
updateFrom(status: status, publishUpdate: true)
updateFrom(status: status)
} catch {
isFavorited.toggle()
favoritesCount += isFavorited ? -1 : 1
objectWillChange.send()
}
}
@ -111,14 +106,12 @@ public final class StatusDataController: StatusDataControlling {
let id = remoteStatus ?? status.id
let endpoint = isReblogged ? Statuses.reblog(id: id) : Statuses.unreblog(id: id)
reblogsCount += isReblogged ? 1 : -1
objectWillChange.send()
do {
let status: Status = try await client.post(endpoint: endpoint)
updateFrom(status: status.reblog ?? status, publishUpdate: true)
updateFrom(status: status.reblog ?? status)
} catch {
isReblogged.toggle()
reblogsCount += isReblogged ? -1 : 1
objectWillChange.send()
}
}
@ -127,13 +120,11 @@ public final class StatusDataController: StatusDataControlling {
isBookmarked.toggle()
let id = remoteStatus ?? status.id
let endpoint = isBookmarked ? Statuses.bookmark(id: id) : Statuses.unbookmark(id: id)
objectWillChange.send()
do {
let status: Status = try await client.post(endpoint: endpoint)
updateFrom(status: status, publishUpdate: true)
updateFrom(status: status)
} catch {
isBookmarked.toggle()
objectWillChange.send()
}
}
}

View file

@ -89,10 +89,11 @@ public struct ExploreView: View {
Text(scope.localizedString)
}
}
.onChange(of: viewModel.searchQuery) { oldValue, newValue in
if oldValue != newValue {
viewModel.search()
}
.task(id: viewModel.searchQuery) {
do {
try await Task.sleep(for: .milliseconds(150))
await viewModel.search()
} catch { }
}
}

View file

@ -54,8 +54,6 @@ import Observation
var trendingStatuses: [Status] = []
var trendingLinks: [Card] = []
var searchScope: SearchScope = .all
private var searchTask: Task<Void, Never>?
init() { }
@ -95,30 +93,24 @@ import Observation
trendingLinks: trendingLinks)
}
func search() {
guard !searchQuery.isEmpty else { return }
isSearching = true
searchTask?.cancel()
searchTask = nil
searchTask = Task {
guard let client else { return }
do {
try await Task.sleep(for: .milliseconds(250))
var results: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery,
type: nil,
offset: nil,
following: nil),
forceVersion: .v2)
let relationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map(\.id)))
results.relationships = relationships
withAnimation {
self.results[searchQuery] = results
isSearching = false
}
} catch {
func search() async {
guard let client else { return }
do {
try await Task.sleep(for: .milliseconds(250))
var results: SearchResults = try await client.get(endpoint: Search.search(query: searchQuery,
type: nil,
offset: nil,
following: nil),
forceVersion: .v2)
let relationships: [Relationship] =
try await client.get(endpoint: Accounts.relationships(ids: results.accounts.map(\.id)))
results.relationships = relationships
withAnimation {
self.results[searchQuery] = results
isSearching = false
}
} catch {
isSearching = false
}
}
}

View file

@ -9,10 +9,10 @@ public struct ListEditView: View {
@EnvironmentObject private var theme: Theme
@Environment(Client.self) private var client
@StateObject private var viewModel: ListEditViewModel
@State private var viewModel: ListEditViewModel
public init(list: Models.List) {
_viewModel = StateObject(wrappedValue: .init(list: list))
_viewModel = .init(initialValue: .init(list: list))
}
public var body: some View {

View file

@ -2,15 +2,16 @@ import Combine
import Models
import Network
import SwiftUI
import Observation
@MainActor
public class ListEditViewModel: ObservableObject {
@Observable public class ListEditViewModel {
let list: Models.List
var client: Client?
@Published var isLoadingAccounts: Bool = true
@Published var accounts: [Account] = []
var isLoadingAccounts: Bool = true
var accounts: [Account] = []
init(list: Models.List) {
self.list = list

View file

@ -11,8 +11,8 @@ public struct NotificationsListView: View {
@Environment(StreamWatcher.self) private var watcher
@Environment(Client.self) private var client
@Environment(RouterPath.self) private var routerPath
@Environment(CurrentAccount.self) private var account
@StateObject private var viewModel = NotificationsViewModel()
@Environment(CurrentAccount.self) private var account
@State private var viewModel = NotificationsViewModel()
let lockedType: Models.Notification.NotificationType?

View file

@ -3,9 +3,10 @@ import Foundation
import Models
import Network
import SwiftUI
import Observation
@MainActor
class NotificationsViewModel: ObservableObject {
@Observable class NotificationsViewModel {
public enum State {
public enum PagingState {
case none, hasNextPage, loadingNextPage
@ -35,8 +36,8 @@ class NotificationsViewModel: ObservableObject {
var currentAccount: CurrentAccount?
@Published var state: State = .loading
@Published var selectedType: Models.Notification.NotificationType? {
var state: State = .loading
var selectedType: Models.Notification.NotificationType? {
didSet {
if oldValue != selectedType {
consolidatedNotifications = []

View file

@ -167,7 +167,7 @@ public struct StatusRowView: View {
.alignmentGuide(.listRowSeparatorLeading) { _ in
-100
}
.environmentObject(
.environment(
StatusDataControllerProvider.shared.dataController(for: viewModel.finalStatus,
client: viewModel.client)
)

View file

@ -7,7 +7,7 @@ import SwiftUI
struct StatusRowActionsView: View {
@EnvironmentObject private var theme: Theme
@Environment(CurrentAccount.self) private var currentAccount
@EnvironmentObject private var statusDataController: StatusDataController
@Environment(StatusDataController.self) private var statusDataController
@EnvironmentObject private var userPreferences: UserPreferences
@Environment(\.isStatusFocused) private var isFocused

View file

@ -12,7 +12,7 @@ struct StatusRowContextMenu: View {
@EnvironmentObject private var preferences: UserPreferences
@Environment(CurrentAccount.self) private var account
@Environment(CurrentInstance.self) private var currentInstance
@EnvironmentObject private var statusDataController: StatusDataController
@Environment(StatusDataController.self) private var statusDataController
var viewModel: StatusRowViewModel

View file

@ -3,10 +3,11 @@ import Env
import Models
import SwiftUI
@MainActor
struct StatusRowDetailView: View {
@Environment(\.openURL) private var openURL
@EnvironmentObject private var statusDataController: StatusDataController
@Environment(StatusDataController.self) private var statusDataController
var viewModel: StatusRowViewModel

View file

@ -7,7 +7,7 @@ struct StatusRowSwipeView: View {
@EnvironmentObject private var theme: Theme
@EnvironmentObject private var preferences: UserPreferences
@Environment(CurrentAccount.self) private var currentAccount
@EnvironmentObject private var statusDataController: StatusDataController
@Environment(StatusDataController.self) private var statusDataController
enum Mode {
case leading, trailing