Duplicate methods to work with Entity.Account
This is preparation, but as you know: Proper Preperation and Planning Prevent Piss Poor Performance
This commit is contained in:
parent
e640befd9e
commit
b92ffe8a46
|
@ -8,6 +8,7 @@
|
|||
import UIKit
|
||||
import CoreDataStack
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
extension DataSourceFacade {
|
||||
static func responseToUserBlockAction(
|
||||
|
@ -29,5 +30,26 @@ extension DataSourceFacade {
|
|||
authenticationBox: authBox
|
||||
)
|
||||
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
|
||||
} // end func
|
||||
}
|
||||
|
||||
static func responseToUserBlockAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
user: Mastodon.Entity.Account
|
||||
) async throws {
|
||||
let selectionFeedbackGenerator = await UISelectionFeedbackGenerator()
|
||||
await selectionFeedbackGenerator.selectionChanged()
|
||||
|
||||
let apiService = dependency.context.apiService
|
||||
let authBox = dependency.authContext.mastodonAuthenticationBox
|
||||
|
||||
_ = try await apiService.toggleBlock(
|
||||
user: user,
|
||||
authenticationBox: authBox
|
||||
)
|
||||
|
||||
try await dependency.context.apiService.getBlocked(
|
||||
authenticationBox: authBox
|
||||
)
|
||||
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,22 @@ extension DataSourceFacade {
|
|||
authenticationBox: dependency.authContext.mastodonAuthenticationBox
|
||||
)
|
||||
dependency.context.authenticationService.fetchFollowingAndBlockedAsync()
|
||||
} // end func
|
||||
}
|
||||
|
||||
static func responseToUserFollowAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
user: Mastodon.Entity.Account
|
||||
) 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()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension DataSourceFacade {
|
||||
|
|
|
@ -64,16 +64,52 @@ extension DataSourceFacade {
|
|||
break //no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
)
|
||||
static func responseToUserViewButtonAction(
|
||||
dependency: NeedsDependency & AuthContextProvider,
|
||||
user: Mastodon.Entity.Account,
|
||||
buttonState: UserView.ButtonState
|
||||
) async throws {
|
||||
switch buttonState {
|
||||
case .follow:
|
||||
try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
user: user
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.append(user.id)
|
||||
|
||||
case .request:
|
||||
try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
user: user
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.append(user.id)
|
||||
case .unfollow:
|
||||
try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
user: user
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followingUserIds.removeAll(where: { $0 == user.id })
|
||||
case .blocked:
|
||||
try await DataSourceFacade.responseToUserBlockAction(
|
||||
dependency: dependency,
|
||||
user: user
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.blockedUserIds.append(user.id)
|
||||
|
||||
case .pending:
|
||||
try await DataSourceFacade.responseToUserFollowAction(
|
||||
dependency: dependency,
|
||||
user: user
|
||||
)
|
||||
|
||||
dependency.authContext.mastodonAuthenticationBox.inMemoryCache.followRequestedUserIDs.removeAll(where: { $0 == user.id })
|
||||
case .none, .loading:
|
||||
break //no-op
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@ import MastodonLocalization
|
|||
import MastodonMeta
|
||||
import MastodonCore
|
||||
import Meta
|
||||
import MastodonSDK
|
||||
|
||||
extension UserView {
|
||||
public func configure(user: MastodonUser, delegate: UserViewDelegate?) {
|
||||
|
@ -63,4 +64,8 @@ extension UserView {
|
|||
.assign(to: \.authorVerifiedLink, on: viewModel)
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
|
||||
func configure(with account: Mastodon.Entity.Account) {
|
||||
//TODO: Implement
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,8 @@ import UIKit
|
|||
import CoreDataStack
|
||||
import MastodonUI
|
||||
import Combine
|
||||
import MastodonCore
|
||||
import MastodonSDK
|
||||
|
||||
extension UserTableViewCell {
|
||||
final class ViewModel {
|
||||
|
@ -72,5 +74,27 @@ extension UserTableViewCell {
|
|||
|
||||
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 user: Mastodon.Entity.Account) {
|
||||
Task {
|
||||
try await DataSourceFacade.responseToUserViewButtonAction(
|
||||
dependency: self,
|
||||
user: user,
|
||||
buttonState: state
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -148,7 +148,98 @@ extension APIService {
|
|||
let response = try result.get()
|
||||
return response
|
||||
}
|
||||
|
||||
|
||||
public func toggleBlock(
|
||||
user: Mastodon.Entity.Account,
|
||||
authenticationBox: MastodonAuthenticationBox
|
||||
) async throws -> Mastodon.Response.Content<Mastodon.Entity.Relationship> {
|
||||
fatalError("Not implemented yet")
|
||||
|
||||
// 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)
|
||||
// }
|
||||
//
|
||||
// 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 {
|
||||
// let response = try await Mastodon.API.Account.unblock(
|
||||
// session: session,
|
||||
// domain: authenticationBox.domain,
|
||||
// accountID: blockContext.targetUserID,
|
||||
// authorization: authenticationBox.userAuthorization
|
||||
// ).singleOutput()
|
||||
// result = .success(response)
|
||||
// } else {
|
||||
// let response = try await Mastodon.API.Account.block(
|
||||
// session: session,
|
||||
// domain: authenticationBox.domain,
|
||||
// accountID: blockContext.targetUserID,
|
||||
// authorization: authenticationBox.userAuthorization
|
||||
// ).singleOutput()
|
||||
// result = .success(response)
|
||||
// }
|
||||
// } 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
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
extension MastodonUser {
|
||||
|
|
|
@ -38,11 +38,11 @@ extension APIService {
|
|||
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)
|
||||
|
@ -66,11 +66,11 @@ extension APIService {
|
|||
)
|
||||
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 {
|
||||
|
@ -85,13 +85,13 @@ extension APIService {
|
|||
} 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(
|
||||
|
@ -108,11 +108,105 @@ extension APIService {
|
|||
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> {
|
||||
fatalError("Not implemented yet")
|
||||
|
||||
/**
|
||||
1. Get relation between me and user
|
||||
2. check if I follow them:
|
||||
if so: unfollow
|
||||
if not: follow
|
||||
3. return result of 2.
|
||||
|
||||
*/
|
||||
|
||||
// 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 toggleShowReblogs(
|
||||
for user: ManagedObjectRecord<MastodonUser>,
|
||||
authenticationBox: MastodonAuthenticationBox
|
||||
|
|
|
@ -13,6 +13,7 @@ import MastodonCore
|
|||
import MastodonMeta
|
||||
import MastodonAsset
|
||||
import MastodonLocalization
|
||||
import MastodonSDK
|
||||
|
||||
extension UserView {
|
||||
public final class ViewModel: ObservableObject {
|
||||
|
@ -26,6 +27,7 @@ extension UserView {
|
|||
@Published public var authorFollowers: Int?
|
||||
@Published public var authorVerifiedLink: String?
|
||||
@Published public var user: MastodonUser?
|
||||
@Published public var account: Mastodon.Entity.Account?
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,9 +12,11 @@ import MastodonAsset
|
|||
import MastodonLocalization
|
||||
import os
|
||||
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)
|
||||
}
|
||||
|
||||
public final class UserView: UIView {
|
||||
|
@ -251,9 +253,12 @@ public extension UserView {
|
|||
}
|
||||
}
|
||||
|
||||
@objc private func didTapButton() {
|
||||
guard let user = viewModel.user else { return }
|
||||
delegate?.userView(self, didTapButtonWith: currentButtonState, for: user)
|
||||
@objc private func didTapFollowButton() {
|
||||
if let user = viewModel.user {
|
||||
delegate?.userView(self, didTapButtonWith: currentButtonState, for: user)
|
||||
} else if let account = viewModel.account {
|
||||
delegate?.userView(self, didTapButtonWith: currentButtonState, for: account)
|
||||
}
|
||||
}
|
||||
|
||||
func setButtonState(_ state: ButtonState) {
|
||||
|
@ -310,7 +315,8 @@ public extension UserView {
|
|||
followButton.configuration?.baseBackgroundColor = .clear
|
||||
}
|
||||
|
||||
followButton.addTarget(self, action: #selector(didTapButton), for: .touchUpInside)
|
||||
followButton.addTarget(self, action: #selector(didTapFollowButton), for: .touchUpInside)
|
||||
followButton.titleLabel?.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .boldSystemFont(ofSize: 15))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue