Remove user from UserItem-lists (IOS-192)

Also: Remove CoreData and replace User with Account in several places
This commit is contained in:
Nathan Mattes 2023-12-14 14:07:42 +01:00
parent 3abb80a5df
commit f373506aa3
20 changed files with 58 additions and 473 deletions

View File

@ -11,7 +11,6 @@ import CoreDataStack
import MastodonSDK
enum UserItem: Hashable {
case user(record: ManagedObjectRecord<MastodonUser>)
case account(account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?)
case bottomLoader
case bottomHeader(text: String)

View File

@ -37,7 +37,7 @@ extension UserSection {
case .account(let account, let relationship):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
guard let me = authContext.mastodonAuthenticationBox.authentication.user(in: context.managedObjectContext) else { return cell }
guard let me = authContext.mastodonAuthenticationBox.authentication.account() else { return cell }
cell.userView.setButtonState(.loading)
cell.configure(
@ -48,27 +48,6 @@ extension UserSection {
delegate: userTableViewCellDelegate
)
return cell
case .user(let record):
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: UserTableViewCell.self), for: indexPath) as! UserTableViewCell
context.managedObjectContext.performAndWait {
guard let user = record.object(in: context.managedObjectContext) else { return }
configure(
context: context,
authContext: authContext,
tableView: tableView,
cell: cell,
viewModel: UserTableViewCell.ViewModel(
user: user,
followedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followingUserIds.eraseToAnyPublisher(),
blockedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$blockedUserIds.eraseToAnyPublisher(),
followRequestedUsers: authContext.mastodonAuthenticationBox.inMemoryCache.$followRequestedUserIDs.eraseToAnyPublisher()
),
userTableViewCellDelegate: userTableViewCellDelegate
)
}
return cell
case .bottomLoader:
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self), for: indexPath) as! TimelineBottomLoaderTableViewCell
@ -82,23 +61,3 @@ extension UserSection {
}
}
}
extension UserSection {
static func configure(
context: AppContext,
authContext: AuthContext,
tableView: UITableView,
cell: UserTableViewCell,
viewModel: UserTableViewCell.ViewModel,
userTableViewCellDelegate: UserTableViewCellDelegate?
) {
cell.configure(
me: authContext.mastodonAuthenticationBox.authentication.user(in: context.managedObjectContext),
tableView: tableView,
viewModel: viewModel,
delegate: userTableViewCellDelegate
)
}
}

View File

@ -13,7 +13,7 @@ import MastodonSDK
extension DataSourceFacade {
static func responseToUserBlockAction(
dependency: NeedsDependency & AuthContextProvider,
user: ManagedObjectRecord<MastodonUser>
account: Mastodon.Entity.Account
) async throws {
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
await selectionFeedbackGenerator.selectionChanged()
@ -22,7 +22,7 @@ extension DataSourceFacade {
let authBox = dependency.authContext.mastodonAuthenticationBox
_ = try await apiService.toggleBlock(
user: user,
account: account,
authenticationBox: authBox
)

View File

@ -15,27 +15,13 @@ import MastodonLocalization
extension DataSourceFacade {
static func responseToUserFollowAction(
dependency: NeedsDependency & AuthContextProvider,
user: ManagedObjectRecord<MastodonUser>
) async throws {
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
await selectionFeedbackGenerator.selectionChanged()
_ = try await dependency.context.apiService.toggleFollow(
user: user,
authenticationBox: dependency.authContext.mastodonAuthenticationBox
)
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
}
static func responseToUserFollowAction(
dependency: NeedsDependency & AuthContextProvider,
user: Mastodon.Entity.Account
account: Mastodon.Entity.Account
) async throws -> Mastodon.Entity.Relationship {
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
await selectionFeedbackGenerator.selectionChanged()
let response = try await dependency.context.apiService.toggleFollow(
user: user,
account: account,
authenticationBox: dependency.authContext.mastodonAuthenticationBox
).value
@ -118,22 +104,12 @@ extension DataSourceFacade {
}
extension DataSourceFacade {
static func responseToShowHideReblogAction(
dependency: NeedsDependency & AuthContextProvider,
account: Mastodon.Entity.Account
) async throws {
#warning("TODO: Implement")
// _ = try await dependency.context.apiService.toggleShowReblogs(
// for: user,
// authenticationBox: dependency.authContext.mastodonAuthenticationBox)
}
static func responseToShowHideReblogAction(
dependency: NeedsDependency & AuthContextProvider,
user: Mastodon.Entity.Account
dependency: NeedsDependency & AuthContextProvider,
account: Mastodon.Entity.Account
) async throws {
_ = try await dependency.context.apiService.toggleShowReblogs(
for: user,
authenticationBox: dependency.authContext.mastodonAuthenticationBox)
_ = try await dependency.context.apiService.toggleShowReblogs(
for: account,
authenticationBox: dependency.authContext.mastodonAuthenticationBox)
}
}

View File

@ -144,20 +144,8 @@ extension DataSourceFacade {
return
}
#warning("TODO: Implement")
await DataSourceFacade.coordinateToProfileScene(provider: provider, domain: "", accountID: mention.id)
// let profileViewModel = ProfileViewModel(
// context: provider.context,
// authContext: provider.authContext,
// account: status.entity.account
// )
//
// _ = provider.coordinator.present(
// scene: .profile(viewModel: profileViewModel),
// from: provider,
// transition: .show
// )
await DataSourceFacade.coordinateToProfileScene(provider: provider, domain: domain, accountID: mention.id)
}
}

View File

@ -354,7 +354,7 @@ extension DataSourceFacade {
break
case .followUser(_):
try await DataSourceFacade.responseToUserFollowAction(dependency: dependency,
user: menuContext.author)
account: menuContext.author)
}
} // end func
}

View File

@ -9,105 +9,46 @@ import MastodonSDK
extension DataSourceFacade {
static func responseToUserViewButtonAction(
dependency: NeedsDependency & AuthContextProvider,
user: ManagedObjectRecord<MastodonUser>,
buttonState: UserView.ButtonState
) async throws {
switch buttonState {
case .follow:
try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
)
if let userObject = user.object(in: dependency.context.managedObjectContext) {
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.append(userObject.id)
}
case .request:
try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
)
if let userObject = user.object(in: dependency.context.managedObjectContext) {
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.append(userObject.id)
}
case .unfollow:
try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
)
if let userObject = user.object(in: dependency.context.managedObjectContext) {
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.removeAll(where: { $0 == userObject.id })
}
case .blocked:
try await DataSourceFacade.responseToUserBlockAction(
dependency: dependency,
user: user
)
if let userObject = user.object(in: dependency.context.managedObjectContext) {
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds.append(userObject.id)
}
case .pending:
try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
)
if let userObject = user.object(in: dependency.context.managedObjectContext) {
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.removeAll(where: { $0 == userObject.id })
}
case .none, .loading:
break //no-op
}
}
static func responseToUserViewButtonAction(
dependency: NeedsDependency & AuthContextProvider,
user: Mastodon.Entity.Account,
account: Mastodon.Entity.Account,
buttonState: UserView.ButtonState
) async throws {
switch buttonState {
case .follow:
_ = try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
account: account
)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.append(user.id)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.append(account.id)
case .request:
_ = try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
account: account
)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.append(user.id)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.append(account.id)
case .unfollow:
_ = try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
account: account
)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.removeAll(where: { $0 == user.id })
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.removeAll(where: { $0 == account.id })
case .blocked:
try await DataSourceFacade.responseToUserBlockAction(
dependency: dependency,
user: user
account: account
)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds.append(user.id)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds.append(account.id)
case .pending:
_ = try await DataSourceFacade.responseToUserFollowAction(
dependency: dependency,
user: user
account: account
)
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.removeAll(where: { $0 == user.id })
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.removeAll(where: { $0 == account.id })
case .none, .loading:
break //no-op
}

View File

@ -99,9 +99,7 @@ extension DiscoveryForYouViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard case let .account(account, _) = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else { return }
Task {
await DataSourceFacade.coordinateToProfileScene(provider: self, account: account)
}
DataSourceFacade.coordinateToProfileScene(provider: self, account: account)
}
}
@ -119,7 +117,7 @@ extension DiscoveryForYouViewController: ProfileCardTableViewCellDelegate {
cell.profileCardView.setButtonState(.loading)
Task {
let newRelationship = try await DataSourceFacade.responseToUserFollowAction(dependency: self, user: account)
let newRelationship = try await DataSourceFacade.responseToUserFollowAction(dependency: self, account: account)
let isMe = (account.id == authContext.mastodonAuthenticationBox.userID)

View File

@ -21,7 +21,7 @@ extension FavoritedByViewController: DataSourceProvider {
}
switch item {
case .user(_), .bottomHeader(_), .bottomLoader:
case .bottomHeader(_), .bottomLoader:
return nil
case .account(let account, let relationship):
return .account(account: account, relationship: relationship)

View File

@ -22,7 +22,7 @@ extension RebloggedByViewController: DataSourceProvider {
}
switch item {
case .user(_), .bottomHeader(_), .bottomLoader:
case .bottomHeader(_), .bottomLoader:
return nil
case .account(let account, let relationship):
return .account(account: account, relationship: relationship)

View File

@ -90,7 +90,7 @@ extension ReportResultViewController {
do {
try await DataSourceFacade.responseToUserFollowAction(
dependency: self,
user: self.viewModel.account
account: self.viewModel.account
)
} catch {
// handle error

View File

@ -44,7 +44,7 @@ extension SearchResultSection {
case .account(let account, let relationship):
let cell = tableView.dequeueReusableCell(withIdentifier: UserTableViewCell.reuseIdentifier, for: indexPath) as! UserTableViewCell
guard let me = authContext.mastodonAuthenticationBox.authentication.user(in: context.managedObjectContext) else { return cell }
guard let me = authContext.mastodonAuthenticationBox.authentication.account() else { return cell }
cell.userView.setButtonState(.loading)
cell.configure(
@ -110,21 +110,4 @@ extension SearchResultSection {
delegate: configuration.statusViewTableViewCellDelegate
)
}
static func configure(
context: AppContext,
authContext: AuthContext,
tableView: UITableView,
cell: UserTableViewCell,
viewModel: UserTableViewCell.ViewModel,
configuration: Configuration
) {
cell.configure(
me: authContext.mastodonAuthenticationBox.authentication.user(in: context.managedObjectContext),
tableView: tableView,
viewModel: viewModel,
delegate: configuration.userTableViewCellDelegate
)
}
}

View File

@ -17,61 +17,9 @@ import MastodonSDK
import MastodonAsset
extension UserView {
public func configure(user: MastodonUser, delegate: UserViewDelegate?) {
self.delegate = delegate
viewModel.user = user
viewModel.account = nil
viewModel.relationship = nil
Publishers.CombineLatest(
user.publisher(for: \.avatar),
UserDefaults.shared.publisher(for: \.preferredStaticAvatar)
)
.map { _ in user.avatarImageURL() }
.assign(to: \.authorAvatarImageURL, on: viewModel)
.store(in: &disposeBag)
// author name
Publishers.CombineLatest(
user.publisher(for: \.displayName),
user.publisher(for: \.emojis)
)
.map { _, emojis in
do {
let content = MastodonContent(content: user.displayNameWithFallback, emojis: emojis.asDictionary)
let metaContent = try MastodonMetaContent.convert(document: content)
return metaContent
} catch {
assertionFailure(error.localizedDescription)
return PlaintextMetaContent(string: user.displayNameWithFallback)
}
}
.assign(to: \.authorName, on: viewModel)
.store(in: &disposeBag)
// author username
user.publisher(for: \.acct)
.map { $0 as String? }
.assign(to: \.authorUsername, on: viewModel)
.store(in: &disposeBag)
user.publisher(for: \.followersCount)
.map { Int($0) }
.assign(to: \.authorFollowers, on: viewModel)
.store(in: &disposeBag)
user.publisher(for: \.fields)
.map { fields in
let firstVerified = fields.first(where: { $0.verifiedAt != nil })
return firstVerified?.value
}
.assign(to: \.authorVerifiedLink, on: viewModel)
.store(in: &disposeBag)
}
func configure(with account: Mastodon.Entity.Account, relationship: Mastodon.Entity.Relationship?, delegate: UserViewDelegate?) {
viewModel.account = account
viewModel.relationship = relationship
viewModel.user = nil
self.delegate = delegate
let authorUsername = PlaintextMetaContent(string: "@\(account.username)")

View File

@ -14,14 +14,14 @@ import MastodonSDK
extension UserTableViewCell {
final class ViewModel {
let user: MastodonUser
let account: Mastodon.Entity.Account
let followedUsers: AnyPublisher<[String], Never>
let blockedUsers: AnyPublisher<[String], Never>
let followRequestedUsers: AnyPublisher<[String], Never>
init(user: MastodonUser, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) {
self.user = user
init(account: Mastodon.Entity.Account, followedUsers: AnyPublisher<[String], Never>, blockedUsers: AnyPublisher<[String], Never>, followRequestedUsers: AnyPublisher<[String], Never>) {
self.account = account
self.followedUsers = followedUsers
self.followRequestedUsers = followRequestedUsers
self.blockedUsers = blockedUsers
@ -32,7 +32,7 @@ extension UserTableViewCell {
extension UserTableViewCell {
func configure(
me: MastodonUser,
me: Mastodon.Entity.Account,
tableView: UITableView,
account: Mastodon.Entity.Account,
relationship: Mastodon.Entity.Relationship?,
@ -45,69 +45,16 @@ extension UserTableViewCell {
self.delegate = delegate
}
func configure(
me: MastodonUser? = nil,
tableView: UITableView,
viewModel: ViewModel,
delegate: UserTableViewCellDelegate?
) {
userView.configure(user: viewModel.user, delegate: delegate)
guard let me = me else {
return userView.setButtonState(.none)
}
if viewModel.user == me {
userView.setButtonState(.none)
} else {
userView.setButtonState(.loading)
}
Publishers.CombineLatest3(
viewModel.followedUsers,
viewModel.followRequestedUsers,
viewModel.blockedUsers
)
.receive(on: DispatchQueue.main)
.sink { [weak self] followed, requested, blocked in
if viewModel.user == me {
self?.userView.setButtonState(.none)
} else if blocked.contains(viewModel.user.id) {
self?.userView.setButtonState(.blocked)
} else if followed.contains(viewModel.user.id) {
self?.userView.setButtonState(.unfollow)
} else if requested.contains(viewModel.user.id) {
self?.userView.setButtonState(.pending)
} else if viewModel.user.locked {
self?.userView.setButtonState(.request)
} else if viewModel.user != me {
self?.userView.setButtonState(.follow)
}
}
.store(in: &disposeBag)
self.delegate = delegate
}
}
extension UserTableViewCellDelegate where Self: NeedsDependency & AuthContextProvider {
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: MastodonUser) {
Task {
try await DataSourceFacade.responseToUserViewButtonAction(
dependency: self,
user: user.asRecord,
buttonState: state
)
}
}
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for account: Mastodon.Entity.Account, me: MastodonUser?) {
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for account: Mastodon.Entity.Account, me: Mastodon.Entity.Account?) {
Task {
await MainActor.run { view.setButtonState(.loading) }
try await DataSourceFacade.responseToUserViewButtonAction(
dependency: self,
user: account,
account: account,
buttonState: state
)

View File

@ -121,7 +121,7 @@ final class SuggestionAccountViewModel: NSObject {
taskGroup.addTask {
try? await DataSourceFacade.responseToUserViewButtonAction(
dependency: dependency,
user: account,
account: account,
buttonState: .follow
)
}

View File

@ -61,40 +61,22 @@ extension APIService {
}
public func toggleBlock(
user: ManagedObjectRecord<MastodonUser>,
account: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
let managedObjectContext = backgroundManagedObjectContext
let blockContext: MastodonBlockContext = try await managedObjectContext.performChanges {
let authentication = authenticationBox.authentication
guard
let user = user.object(in: managedObjectContext),
let me = authentication.user(in: managedObjectContext)
else {
throw APIError.implicit(.badRequest)
}
let isBlocking = user.blockingBy.contains(me)
let isFollowing = user.followingBy.contains(me)
// toggle block state
user.update(isBlocking: !isBlocking, by: me)
// update follow state implicitly
if !isBlocking {
// will do block action. set to unfollow
user.update(isFollowing: false, by: me)
}
guard let me = authenticationBox.authentication.account(),
let relationship = try await relationship(forAccounts: [account], authenticationBox: authenticationBox).value.first
else { throw APIError.implicit(.badRequest) }
let blockContext = MastodonBlockContext(
sourceUserID: me.id,
targetUserID: account.id,
targetUsername: account.username,
isBlocking: relationship.blocking,
isFollowing: relationship.following
)
return MastodonBlockContext(
sourceUserID: me.id,
targetUserID: user.id,
targetUsername: user.username,
isBlocking: isBlocking,
isFollowing: isFollowing
)
}
let result: Result<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>
do {
if blockContext.isBlocking {
@ -117,34 +99,7 @@ extension APIService {
} catch {
result = .failure(error)
}
try await managedObjectContext.performChanges {
let authentication = authenticationBox.authentication
guard
let user = user.object(in: managedObjectContext),
let me = authentication.user(in: managedObjectContext)
else { return }
switch result {
case .success(let response):
let relationship = response.value
Persistence.MastodonUser.update(
mastodonUser: user,
context: Persistence.MastodonUser.RelationshipContext(
entity: relationship,
me: me,
networkDate: response.networkDate
)
)
case .failure:
// rollback
user.update(isBlocking: blockContext.isBlocking, by: me)
user.update(isFollowing: blockContext.isFollowing, by: me)
}
}
let response = try result.get()
return response
}

View File

@ -30,95 +30,11 @@ extension APIService {
/// - activeMastodonAuthenticationBox: `AuthenticationService.MastodonAuthenticationBox`
/// - Returns: publisher for `Relationship`
public func toggleFollow(
user: ManagedObjectRecord<MastodonUser>,
account: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
let managedObjectContext = backgroundManagedObjectContext
let _followContext: MastodonFollowContext? = try await managedObjectContext.performChanges {
guard let me = authenticationBox.authentication.user(in: managedObjectContext) else { return nil }
guard let user = user.object(in: managedObjectContext) else { return nil }
let isFollowing = user.followingBy.contains(me)
let isPending = user.followRequestedBy.contains(me)
let needsUnfollow = isFollowing || isPending
if needsUnfollow {
// unfollow
user.update(isFollowing: false, by: me)
user.update(isFollowRequested: false, by: me)
} else {
// follow
if user.locked {
user.update(isFollowing: false, by: me)
user.update(isFollowRequested: true, by: me)
} else {
user.update(isFollowing: true, by: me)
user.update(isFollowRequested: false, by: me)
}
}
let context = MastodonFollowContext(
sourceUserID: me.id,
targetUserID: user.id,
isFollowing: isFollowing,
isPending: isPending,
needsUnfollow: needsUnfollow
)
return context
}
guard let followContext = _followContext else {
throw APIError.implicit(.badRequest)
}
// request follow or unfollow
let result: Result<Mastodon.Response.Content<Mastodon.Entity.Relationship>, Error>
do {
let response = try await Mastodon.API.Account.follow(
session: session,
domain: authenticationBox.domain,
accountID: followContext.targetUserID,
followQueryType: followContext.needsUnfollow ? .unfollow : .follow(query: .init()),
authorization: authenticationBox.userAuthorization
).singleOutput()
result = .success(response)
} catch {
result = .failure(error)
}
// update friendship state
try await managedObjectContext.performChanges {
guard let me = authenticationBox.authentication.user(in: managedObjectContext),
let user = user.object(in: managedObjectContext)
else { return }
switch result {
case .success(let response):
Persistence.MastodonUser.update(
mastodonUser: user,
context: Persistence.MastodonUser.RelationshipContext(
entity: response.value,
me: me,
networkDate: response.networkDate
)
)
case .failure:
// rollback
user.update(isFollowing: followContext.isFollowing, by: me)
user.update(isFollowRequested: followContext.isPending, by: me)
}
}
let response = try result.get()
return response
}
public func toggleFollow(
user: Mastodon.Entity.Account,
authenticationBox: MastodonAuthenticationBox
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
guard let relationship = try await relationship(forAccounts: [user], authenticationBox: authenticationBox).value.first else {
guard let relationship = try await relationship(forAccounts: [account], authenticationBox: authenticationBox).value.first else {
throw APIError.implicit(.badRequest)
}
@ -129,14 +45,14 @@ extension APIService {
response = try await Mastodon.API.Account.unfollow(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
accountID: account.id,
authorization: authenticationBox.userAuthorization
).singleOutput()
} else {
response = try await Mastodon.API.Account.follow(
session: session,
domain: authenticationBox.domain,
accountID: user.id,
accountID: account.id,
followQueryType: .follow(query: .init()),
authorization: authenticationBox.userAuthorization
).singleOutput()

View File

@ -32,28 +32,7 @@ extension APIService {
query: query,
authorization: authorization
).singleOutput()
let managedObjectContext = self.backgroundManagedObjectContext
try await managedObjectContext.performChanges {
let me = authenticationBox.authentication.user(in: managedObjectContext)
for entity in response.value {
let result = Persistence.MastodonUser.createOrMerge(
in: managedObjectContext,
context: Persistence.MastodonUser.PersistContext(
domain: domain,
entity: entity,
cache: nil,
networkDate: response.networkDate
)
)
let user = result.user
me?.update(isFollowing: true, by: user)
}
}
return response
}
}

View File

@ -26,7 +26,6 @@ extension UserView {
@Published public var authorUsername: String?
@Published public var authorFollowers: Int?
@Published public var authorVerifiedLink: String?
@Published public var user: MastodonUser?
@Published public var account: Mastodon.Entity.Account?
@Published public var relationship: Mastodon.Entity.Relationship?
}

View File

@ -15,8 +15,7 @@ import CoreDataStack
import MastodonSDK
public protocol UserViewDelegate: AnyObject {
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: MastodonUser)
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: Mastodon.Entity.Account, me: MastodonUser?)
func userView(_ view: UserView, didTapButtonWith state: UserView.ButtonState, for user: Mastodon.Entity.Account, me: Mastodon.Entity.Account?)
}
public final class UserView: UIView {
@ -255,9 +254,7 @@ public extension UserView {
}
@objc private func didTapFollowButton() {
if let user = viewModel.user {
delegate?.userView(self, didTapButtonWith: currentButtonState, for: user)
} else if let account = viewModel.account {
if let account = viewModel.account {
delegate?.userView(self, didTapButtonWith: currentButtonState, for: account, me: nil)
}
}