mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-03 16:10:20 +00:00
Removed Pill Avatar + @room is not displayed among suggestions for DM (#1968)
* removed pill avatar * completion suggestion service shows @room as first and only if not a DM * code improvement
This commit is contained in:
@@ -20,11 +20,8 @@ import Foundation
|
|||||||
@MainActor
|
@MainActor
|
||||||
final class PillContext: ObservableObject {
|
final class PillContext: ObservableObject {
|
||||||
struct PillViewState: Equatable {
|
struct PillViewState: Equatable {
|
||||||
let contentID: String
|
|
||||||
let isOwnMention: Bool
|
let isOwnMention: Bool
|
||||||
let name: String?
|
|
||||||
let displayText: String
|
let displayText: String
|
||||||
let avatarURL: URL?
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Published private(set) var viewState: PillViewState
|
@Published private(set) var viewState: PillViewState
|
||||||
@@ -36,23 +33,29 @@ final class PillContext: ObservableObject {
|
|||||||
case let .user(id):
|
case let .user(id):
|
||||||
let isOwnMention = id == roomContext.viewState.ownUserID
|
let isOwnMention = id == roomContext.viewState.ownUserID
|
||||||
if let profile = roomContext.viewState.members[id] {
|
if let profile = roomContext.viewState.members[id] {
|
||||||
let name = profile.displayName ?? id
|
var name = id
|
||||||
viewState = PillViewState(contentID: id, isOwnMention: isOwnMention, name: name, displayText: name, avatarURL: profile.avatarURL)
|
if let displayName = profile.displayName {
|
||||||
|
name = "@\(displayName)"
|
||||||
|
}
|
||||||
|
viewState = PillViewState(isOwnMention: isOwnMention, displayText: name)
|
||||||
} else {
|
} else {
|
||||||
viewState = PillViewState(contentID: id, isOwnMention: isOwnMention, name: nil, displayText: id, avatarURL: nil)
|
viewState = PillViewState(isOwnMention: isOwnMention, displayText: id)
|
||||||
cancellable = roomContext.$viewState.sink { [weak self] viewState in
|
cancellable = roomContext.$viewState.sink { [weak self] viewState in
|
||||||
guard let self else {
|
guard let self else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if let profile = viewState.members[id] {
|
if let profile = viewState.members[id] {
|
||||||
let name = profile.displayName ?? id
|
var name = id
|
||||||
self.viewState = PillViewState(contentID: id, isOwnMention: isOwnMention, name: name, displayText: name, avatarURL: profile.avatarURL)
|
if let displayName = profile.displayName {
|
||||||
|
name = "@\(displayName)"
|
||||||
|
}
|
||||||
|
self.viewState = PillViewState(isOwnMention: isOwnMention, displayText: name)
|
||||||
cancellable = nil
|
cancellable = nil
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case .allUsers:
|
case .allUsers:
|
||||||
viewState = PillViewState(contentID: roomContext.viewState.roomID, isOwnMention: true, name: roomContext.viewState.roomTitle, displayText: PillConstants.atRoom, avatarURL: roomContext.viewState.roomAvatarURL)
|
viewState = PillViewState(isOwnMention: true, displayText: PillConstants.atRoom)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,16 +74,16 @@ extension PillContext {
|
|||||||
case .loadUser(let isOwn):
|
case .loadUser(let isOwn):
|
||||||
pillType = .user(userID: testID)
|
pillType = .user(userID: testID)
|
||||||
let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body)))
|
let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body)))
|
||||||
viewModel.viewState = PillViewState(contentID: testID, isOwnMention: isOwn, name: nil, displayText: testID, avatarURL: nil)
|
viewModel.viewState = PillViewState(isOwnMention: isOwn, displayText: testID)
|
||||||
Task {
|
Task {
|
||||||
try? await Task.sleep(for: .seconds(2))
|
try? await Task.sleep(for: .seconds(2))
|
||||||
viewModel.viewState = PillViewState(contentID: "@test:test.com", isOwnMention: isOwn, name: nil, displayText: "Test Long Display Text", avatarURL: URL.documentsDirectory)
|
viewModel.viewState = PillViewState(isOwnMention: isOwn, displayText: "@Test Long Display Text")
|
||||||
}
|
}
|
||||||
return viewModel
|
return viewModel
|
||||||
case .loadedUser(let isOwn):
|
case .loadedUser(let isOwn):
|
||||||
pillType = .user(userID: "@test:test.com")
|
pillType = .user(userID: "@test:test.com")
|
||||||
let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body)))
|
let viewModel = PillContext(roomContext: RoomScreenViewModel.mock.context, data: PillTextAttachmentData(type: pillType, font: .preferredFont(forTextStyle: .body)))
|
||||||
viewModel.viewState = PillViewState(contentID: "@test:test.com", isOwnMention: isOwn, name: nil, displayText: "Very Very Long Test Display Text", avatarURL: URL.documentsDirectory)
|
viewModel.viewState = PillViewState(isOwnMention: isOwn, displayText: "@Very Very Long Test Display Text")
|
||||||
return viewModel
|
return viewModel
|
||||||
case .allUsers:
|
case .allUsers:
|
||||||
pillType = .allUsers
|
pillType = .allUsers
|
||||||
|
|||||||
@@ -31,20 +31,17 @@ struct PillView: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
HStack(spacing: 2) {
|
Text(context.viewState.displayText)
|
||||||
LoadableAvatarImage(url: context.viewState.avatarURL, name: context.viewState.name, contentID: context.viewState.contentID, avatarSize: .custom(16), imageProvider: imageProvider)
|
.font(.compound.bodyLGSemibold)
|
||||||
Text(context.viewState.displayText)
|
.foregroundColor(textColor)
|
||||||
.font(.compound.bodyLGSemibold)
|
.lineLimit(1)
|
||||||
.foregroundColor(textColor)
|
.padding(.leading, 4)
|
||||||
.lineLimit(1)
|
.padding(.trailing, 6)
|
||||||
}
|
.padding(.vertical, 1)
|
||||||
.padding(.leading, 4)
|
.background { Capsule().foregroundColor(backgroundColor) }
|
||||||
.padding(.trailing, 6)
|
.onChange(of: context.viewState.displayText) { _ in
|
||||||
.padding(.vertical, 1)
|
didChangeText()
|
||||||
.background { Capsule().foregroundColor(backgroundColor) }
|
}
|
||||||
.onChange(of: context.viewState.displayText) { _ in
|
|
||||||
didChangeText()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ import Combine
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
||||||
|
private let roomProxy: RoomProxyProtocol
|
||||||
private var canMentionAllUsers = false
|
private var canMentionAllUsers = false
|
||||||
let areSuggestionsEnabled: Bool
|
let areSuggestionsEnabled: Bool
|
||||||
private(set) var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> = Empty().eraseToAnyPublisher()
|
private(set) var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> = Empty().eraseToAnyPublisher()
|
||||||
@@ -25,6 +26,7 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
|||||||
private let suggestionTriggerSubject = CurrentValueSubject<SuggestionPattern?, Never>(nil)
|
private let suggestionTriggerSubject = CurrentValueSubject<SuggestionPattern?, Never>(nil)
|
||||||
|
|
||||||
init(roomProxy: RoomProxyProtocol, areSuggestionsEnabled: Bool) {
|
init(roomProxy: RoomProxyProtocol, areSuggestionsEnabled: Bool) {
|
||||||
|
self.roomProxy = roomProxy
|
||||||
self.areSuggestionsEnabled = areSuggestionsEnabled
|
self.areSuggestionsEnabled = areSuggestionsEnabled
|
||||||
guard areSuggestionsEnabled else {
|
guard areSuggestionsEnabled else {
|
||||||
return
|
return
|
||||||
@@ -32,7 +34,8 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
|||||||
suggestionsPublisher = suggestionTriggerSubject
|
suggestionsPublisher = suggestionTriggerSubject
|
||||||
.combineLatest(roomProxy.members)
|
.combineLatest(roomProxy.members)
|
||||||
.map { [weak self] suggestionPattern, members -> [SuggestionItem] in
|
.map { [weak self] suggestionPattern, members -> [SuggestionItem] in
|
||||||
guard let suggestionPattern else {
|
guard let self,
|
||||||
|
let suggestionPattern else {
|
||||||
return []
|
return []
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -47,10 +50,11 @@ final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
|||||||
}
|
}
|
||||||
return SuggestionItem.user(item: .init(id: member.userID, displayName: member.displayName, avatarURL: member.avatarURL))
|
return SuggestionItem.user(item: .init(id: member.userID, displayName: member.displayName, avatarURL: member.avatarURL))
|
||||||
}
|
}
|
||||||
if self?.canMentionAllUsers == true,
|
if self.canMentionAllUsers,
|
||||||
|
!self.roomProxy.isEncryptedOneToOneRoom,
|
||||||
Self.isIncluded(searchText: suggestionPattern.text, userID: PillConstants.atRoom, displayName: PillConstants.everyone) {
|
Self.isIncluded(searchText: suggestionPattern.text, userID: PillConstants.atRoom, displayName: PillConstants.everyone) {
|
||||||
membersSuggestion
|
membersSuggestion
|
||||||
.append(SuggestionItem.allUsers(item: .allUsersMention(roomAvatar: roomProxy.avatarURL)))
|
.insert(SuggestionItem.allUsers(item: .allUsersMention(roomAvatar: self.roomProxy.avatarURL)), at: 0)
|
||||||
}
|
}
|
||||||
return membersSuggestion
|
return membersSuggestion
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -102,9 +102,9 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
|||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
|
|
||||||
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||||
suggestions == [.user(item: .init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)),
|
suggestions == [.allUsers(item: .allUsersMention(roomAvatar: nil)),
|
||||||
.user(item: .init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL)),
|
.user(item: .init(id: alice.userID, displayName: alice.displayName, avatarURL: alice.avatarURL)),
|
||||||
.allUsers(item: .allUsersMention(roomAvatar: nil))]
|
.user(item: .init(id: bob.userID, displayName: bob.displayName, avatarURL: bob.avatarURL))]
|
||||||
}
|
}
|
||||||
service.setSuggestionTrigger(.init(type: .user, text: ""))
|
service.setSuggestionTrigger(.init(type: .user, text: ""))
|
||||||
try await deferred.fulfill()
|
try await deferred.fulfill()
|
||||||
|
|||||||
@@ -37,9 +37,6 @@ class PillContextTests: XCTestCase {
|
|||||||
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .user(userID: id), font: .preferredFont(forTextStyle: .body)))
|
||||||
|
|
||||||
XCTAssertFalse(context.viewState.isOwnMention)
|
XCTAssertFalse(context.viewState.isOwnMention)
|
||||||
XCTAssertNil(context.viewState.avatarURL)
|
|
||||||
XCTAssertNil(context.viewState.name)
|
|
||||||
XCTAssertEqual(context.viewState.contentID, id)
|
|
||||||
XCTAssertEqual(context.viewState.displayText, id)
|
XCTAssertEqual(context.viewState.displayText, id)
|
||||||
|
|
||||||
let name = "Mr. Test"
|
let name = "Mr. Test"
|
||||||
@@ -48,10 +45,7 @@ class PillContextTests: XCTestCase {
|
|||||||
await Task.yield()
|
await Task.yield()
|
||||||
|
|
||||||
XCTAssertFalse(context.viewState.isOwnMention)
|
XCTAssertFalse(context.viewState.isOwnMention)
|
||||||
XCTAssertEqual(context.viewState.avatarURL, avatarURL)
|
XCTAssertEqual(context.viewState.displayText, "@\(name)")
|
||||||
XCTAssertEqual(context.viewState.name, name)
|
|
||||||
XCTAssertEqual(context.viewState.contentID, id)
|
|
||||||
XCTAssertEqual(context.viewState.displayText, name)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func testOwnUser() async throws {
|
func testOwnUser() async throws {
|
||||||
@@ -90,9 +84,6 @@ class PillContextTests: XCTestCase {
|
|||||||
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
|
let context = PillContext(roomContext: mock.context, data: PillTextAttachmentData(type: .allUsers, font: .preferredFont(forTextStyle: .body)))
|
||||||
|
|
||||||
XCTAssertTrue(context.viewState.isOwnMention)
|
XCTAssertTrue(context.viewState.isOwnMention)
|
||||||
XCTAssertEqual(context.viewState.avatarURL, avatarURL)
|
XCTAssertEqual(context.viewState.displayText, PillConstants.atRoom)
|
||||||
XCTAssertEqual(context.viewState.name, displayName)
|
|
||||||
XCTAssertEqual(context.viewState.contentID, id)
|
|
||||||
XCTAssertEqual(context.viewState.displayText, "@room")
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:1a15ca8e95ef692687c5b1eede5d0bd6f7fff14b544100928dd409cd6a48d66d
|
oid sha256:b832b8fc74a6a05083c6d493bb10ea1e50698523511918fefb4f09749276b9a0
|
||||||
size 62925
|
size 62612
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:e28c9283ff63ad76753b6ad671d996034c07e453e44345cbac176dcf4b433c73
|
oid sha256:cb1c8657a870af18a771b7a6b1be6c732ff2e9dfb4b69a558f453ce16d8711e7
|
||||||
size 61442
|
size 60309
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:b78e02b2c47f049fa5e9c5802d76572696d497cd9a09cdb4a05edcb60b1da2df
|
oid sha256:838977457413677c95b62440aba60f39767b5c57c2dc8bc04db17604836961bf
|
||||||
size 66669
|
size 66094
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:bd550435f2618862e8338704605a98f0471aa49a23425ccfbfc1487ad339279c
|
oid sha256:b0a781a2db50c0e6b675fe4253421517bdb7c39584b0d810356e976a0dbf7e0e
|
||||||
size 66822
|
size 66299
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:9fd608f61a0055a49ad6b93a2db812c9a6fb60444a12699bffd78b05d61f3ee5
|
oid sha256:dc295464d789704bef51b0613c6d62a6f4b2273d2468a8c985db64065317b42e
|
||||||
size 63623
|
size 62830
|
||||||
|
|||||||
@@ -1,3 +1,3 @@
|
|||||||
version https://git-lfs.github.com/spec/v1
|
version https://git-lfs.github.com/spec/v1
|
||||||
oid sha256:ffe228e557bf1c029f5b07c6e187db1413cedae314747241c7c03cbcb291b240
|
oid sha256:dd328f4947f5550ac584574b69eec3c2de4f06d90c9fefabe19a36b039ef0ec0
|
||||||
size 63702
|
size 62922
|
||||||
|
|||||||
Reference in New Issue
Block a user