forked from shadowfacts/Tusker
Use AnyAccount instead of EitherAccount for compose autocomplete
This commit is contained in:
parent
8f8d50efbd
commit
80c4fcce82
|
@ -48,7 +48,7 @@ struct ComposeAutocompleteMentionsView: View {
|
|||
@ObservedObject private var preferences = Preferences.shared
|
||||
|
||||
// can't use AccountProtocol because of associated type requirements
|
||||
@State private var accounts: [EitherAccount] = []
|
||||
@State private var accounts: [AnyAccount] = []
|
||||
|
||||
@State private var searchRequest: URLSessionTask?
|
||||
|
||||
|
@ -56,26 +56,20 @@ struct ComposeAutocompleteMentionsView: View {
|
|||
ScrollView(.horizontal) {
|
||||
// can't use LazyHStack because changing the contents of the ForEach causes the ScrollView to hang
|
||||
HStack(spacing: 8) {
|
||||
ForEach(accounts, id: \.id) { (account) in
|
||||
ForEach(accounts, id: \.value.id) { (account) in
|
||||
Button {
|
||||
uiState.currentInput?.autocomplete(with: "@\(account.acct)")
|
||||
uiState.currentInput?.autocomplete(with: "@\(account.value.acct)")
|
||||
} label: {
|
||||
HStack(spacing: 4) {
|
||||
ComposeAvatarImageView(url: account.avatar)
|
||||
ComposeAvatarImageView(url: account.value.avatar)
|
||||
.frame(width: 30, height: 30)
|
||||
.cornerRadius(preferences.avatarStyle.cornerRadiusFraction * 30)
|
||||
|
||||
VStack(alignment: .leading) {
|
||||
switch account {
|
||||
case let .pachyderm(underlying):
|
||||
AccountDisplayNameLabel(account: underlying, fontSize: 14)
|
||||
.foregroundColor(Color(UIColor.label))
|
||||
case let .coreData(underlying):
|
||||
AccountDisplayNameLabel(account: underlying, fontSize: 14)
|
||||
.foregroundColor(Color(UIColor.label))
|
||||
}
|
||||
AccountDisplayNameLabel(account: account.value, fontSize: 14)
|
||||
.foregroundColor(Color(UIColor.label))
|
||||
|
||||
Text(verbatim: "@\(account.acct)")
|
||||
Text(verbatim: "@\(account.value.acct)")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(Color(UIColor.label))
|
||||
}
|
||||
|
@ -110,7 +104,7 @@ struct ComposeAutocompleteMentionsView: View {
|
|||
request.predicate = NSPredicate(format: "displayName LIKE %@ OR acct LIKE %@", wildcardedQuery, wildcardedQuery)
|
||||
|
||||
if let results = try? mastodonController.persistentContainer.viewContext.fetch(request) {
|
||||
loadAccounts(results.map { .coreData($0) }, query: query)
|
||||
loadAccounts(results.map { .init(value: $0) }, query: query)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,27 +125,27 @@ struct ComposeAutocompleteMentionsView: View {
|
|||
DispatchQueue.main.async {
|
||||
// if the query has changed, don't bother loading the now-outdated results
|
||||
if case .mention(query) = uiState.autocompleteState {
|
||||
self.loadAccounts(accounts.map { .pachyderm($0) }, query: query)
|
||||
self.loadAccounts(accounts.map { .init(value: $0) }, query: query)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loadAccounts(_ accounts: [EitherAccount], query: String) {
|
||||
private func loadAccounts(_ accounts: [AnyAccount], query: String) {
|
||||
// when sorting account suggestions, ignore the domain component of the acct unless the user is typing it themself
|
||||
let ignoreDomain = !query.contains("@")
|
||||
|
||||
self.accounts =
|
||||
accounts.map { (account: EitherAccount) -> (EitherAccount, (matched: Bool, score: Int)) in
|
||||
let fuzzyStr = ignoreDomain ? String(account.acct.split(separator: "@").first!) : account.acct
|
||||
accounts.map { (account) -> (AnyAccount, (matched: Bool, score: Int)) in
|
||||
let fuzzyStr = ignoreDomain ? String(account.value.acct.split(separator: "@").first!) : account.value.acct
|
||||
let res = (account, FuzzyMatcher.match(pattern: query, str: fuzzyStr))
|
||||
return res
|
||||
}
|
||||
.filter(\.1.matched)
|
||||
.map { (account, res) -> (EitherAccount, Int) in
|
||||
.map { (account, res) -> (AnyAccount, Int) in
|
||||
// give higher weight to accounts that the user follows or is followed by
|
||||
var score = res.score
|
||||
if let relationship = mastodonController.persistentContainer.relationship(forAccount: account.id) {
|
||||
if let relationship = mastodonController.persistentContainer.relationship(forAccount: account.value.id) {
|
||||
if relationship.following {
|
||||
score += 3
|
||||
}
|
||||
|
@ -165,39 +159,11 @@ struct ComposeAutocompleteMentionsView: View {
|
|||
.map(\.0)
|
||||
}
|
||||
|
||||
private enum EitherAccount: Equatable {
|
||||
case pachyderm(Account)
|
||||
case coreData(AccountMO)
|
||||
private struct AnyAccount: Equatable {
|
||||
let value: any AccountProtocol
|
||||
|
||||
var id: String {
|
||||
switch self {
|
||||
case let .pachyderm(account):
|
||||
return account.id
|
||||
case let .coreData(account):
|
||||
return account.id
|
||||
}
|
||||
}
|
||||
|
||||
var acct: String {
|
||||
switch self {
|
||||
case let .pachyderm(account):
|
||||
return account.acct
|
||||
case let .coreData(account):
|
||||
return account.acct
|
||||
}
|
||||
}
|
||||
|
||||
var avatar: URL? {
|
||||
switch self {
|
||||
case let .pachyderm(account):
|
||||
return account.avatar
|
||||
case let .coreData(account):
|
||||
return account.avatar
|
||||
}
|
||||
}
|
||||
|
||||
static func ==(lhs: EitherAccount, rhs: EitherAccount) -> Bool {
|
||||
return lhs.id == rhs.id
|
||||
static func ==(lhs: AnyAccount, rhs: AnyAccount) -> Bool {
|
||||
return lhs.value.id == rhs.value.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,13 +12,13 @@ import WebURLFoundationExtras
|
|||
|
||||
private let emojiRegex = try! NSRegularExpression(pattern: ":(\\w+):", options: [])
|
||||
|
||||
struct AccountDisplayNameLabel<Account: AccountProtocol>: View {
|
||||
let account: Account
|
||||
struct AccountDisplayNameLabel: View {
|
||||
let account: any AccountProtocol
|
||||
let fontSize: Int
|
||||
@State var text: Text
|
||||
@State var emojiRequests = [ImageCache.Request]()
|
||||
|
||||
init(account: Account, fontSize: Int) {
|
||||
init(account: any AccountProtocol, fontSize: Int) {
|
||||
self.account = account
|
||||
self.fontSize = fontSize
|
||||
let name = account.displayName.isEmpty ? account.username : account.displayName
|
||||
|
|
Loading…
Reference in New Issue