mirror of
https://github.com/element-hq/element-x-ios.git
synced 2025-03-10 21:39:12 +00:00
Resizable Composer With Completion Suggestion View (#1971)
* resizable composer with suggestions view * FF cleanup * removing the view when the vertical size is compact * merge conflict fix * done * solving a conflict * Update ElementX/Sources/Screens/ComposerToolbar/View/CompletionSuggestionView.swift Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com> * pr suggestion --------- Co-authored-by: Doug <6060466+pixlwave@users.noreply.github.com>
This commit is contained in:
parent
84a16091b2
commit
0b31446817
@ -337,7 +337,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
let timelineItemFactory = RoomTimelineItemFactory(userID: userID,
|
||||
mediaProvider: userSession.mediaProvider,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: appSettings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder(mentionsEnabled: appSettings.mentionsEnabled)),
|
||||
mentionBuilder: MentionBuilder()),
|
||||
stateEventStringBuilder: RoomStateEventStringBuilder(userID: userID),
|
||||
appSettings: appSettings)
|
||||
|
||||
@ -351,7 +351,7 @@ class RoomFlowCoordinator: FlowCoordinatorProtocol {
|
||||
|
||||
analytics.trackViewRoom(isDM: roomProxy.isDirect, isSpace: roomProxy.isSpace)
|
||||
|
||||
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy, areSuggestionsEnabled: appSettings.mentionsEnabled)
|
||||
let completionSuggestionService = CompletionSuggestionService(roomProxy: roomProxy)
|
||||
|
||||
let parameters = RoomScreenCoordinatorParameters(roomProxy: roomProxy,
|
||||
timelineController: timelineController,
|
||||
|
@ -304,7 +304,7 @@ class UserSessionFlowCoordinator: FlowCoordinatorProtocol {
|
||||
private func presentHomeScreen() {
|
||||
let parameters = HomeScreenCoordinatorParameters(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled)),
|
||||
mentionBuilder: MentionBuilder()),
|
||||
bugReportService: bugReportService,
|
||||
navigationStackCoordinator: detailNavigationStackCoordinator,
|
||||
selectedRoomPublisher: selectedRoomSubject.asCurrentValuePublisher())
|
||||
|
@ -686,11 +686,6 @@ class BugReportServiceMock: BugReportServiceProtocol {
|
||||
}
|
||||
}
|
||||
class CompletionSuggestionServiceMock: CompletionSuggestionServiceProtocol {
|
||||
var areSuggestionsEnabled: Bool {
|
||||
get { return underlyingAreSuggestionsEnabled }
|
||||
set(value) { underlyingAreSuggestionsEnabled = value }
|
||||
}
|
||||
var underlyingAreSuggestionsEnabled: Bool!
|
||||
var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> {
|
||||
get { return underlyingSuggestionsPublisher }
|
||||
set(value) { underlyingSuggestionsPublisher = value }
|
||||
|
@ -18,15 +18,7 @@ import Foundation
|
||||
import UIKit
|
||||
|
||||
struct MentionBuilder: MentionBuilderProtocol {
|
||||
// Can be removed when mentions are enabled by default
|
||||
let mentionsEnabled: Bool
|
||||
|
||||
func handleUserMention(for attributedString: NSMutableAttributedString, in range: NSRange, url: URL, userID: String) {
|
||||
guard mentionsEnabled else {
|
||||
attributedString.addAttributes([.MatrixUserID: userID], range: range)
|
||||
return
|
||||
}
|
||||
|
||||
let attributes = attributedString.attributes(at: 0, longestEffectiveRange: nil, in: range)
|
||||
let font = attributes[.font] as? UIFont ?? .preferredFont(forTextStyle: .body)
|
||||
let blockquote = attributes[.MatrixBlockquote]
|
||||
@ -48,10 +40,6 @@ struct MentionBuilder: MentionBuilderProtocol {
|
||||
}
|
||||
|
||||
func handleAllUsersMention(for attributedString: NSMutableAttributedString, in range: NSRange) {
|
||||
guard mentionsEnabled else {
|
||||
return
|
||||
}
|
||||
|
||||
let attributes = attributedString.attributes(at: 0, longestEffectiveRange: nil, in: range)
|
||||
let font = attributes[.font] as? UIFont ?? .preferredFont(forTextStyle: .body)
|
||||
let blockquote = attributes[.MatrixBlockquote]
|
||||
|
@ -177,7 +177,7 @@ struct MessageText_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
private static let htmlStringWithList = "<p>This is a list</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n<li>And number 3</li>\n</ul>\n"
|
||||
|
||||
private static let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true))
|
||||
private static let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
||||
|
||||
static var attachmentPreview: some View {
|
||||
MessageText(attributedString: attributedStringWithAttachment)
|
||||
|
@ -80,7 +80,7 @@ struct ShimmerOverlay_Previews: PreviewProvider, TestablePreview {
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled)),
|
||||
mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
@ -20,17 +20,12 @@ import Foundation
|
||||
final class CompletionSuggestionService: CompletionSuggestionServiceProtocol {
|
||||
private let roomProxy: RoomProxyProtocol
|
||||
private var canMentionAllUsers = false
|
||||
let areSuggestionsEnabled: Bool
|
||||
private(set) var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> = Empty().eraseToAnyPublisher()
|
||||
|
||||
private let suggestionTriggerSubject = CurrentValueSubject<SuggestionPattern?, Never>(nil)
|
||||
|
||||
init(roomProxy: RoomProxyProtocol, areSuggestionsEnabled: Bool) {
|
||||
init(roomProxy: RoomProxyProtocol) {
|
||||
self.roomProxy = roomProxy
|
||||
self.areSuggestionsEnabled = areSuggestionsEnabled
|
||||
guard areSuggestionsEnabled else {
|
||||
return
|
||||
}
|
||||
suggestionsPublisher = suggestionTriggerSubject
|
||||
.combineLatest(roomProxy.members)
|
||||
.map { [weak self] suggestionPattern, members -> [SuggestionItem] in
|
||||
|
@ -18,8 +18,6 @@ import Combine
|
||||
|
||||
// sourcery: AutoMockable
|
||||
protocol CompletionSuggestionServiceProtocol {
|
||||
// To be removed once we suggestions and mentions are always enabled
|
||||
var areSuggestionsEnabled: Bool { get }
|
||||
var suggestionsPublisher: AnyPublisher<[SuggestionItem], Never> { get }
|
||||
|
||||
func setSuggestionTrigger(_ suggestionTrigger: SuggestionPattern?)
|
||||
@ -27,13 +25,11 @@ protocol CompletionSuggestionServiceProtocol {
|
||||
|
||||
extension CompletionSuggestionServiceMock {
|
||||
struct CompletionSuggestionServiceMockConfiguration {
|
||||
var areSuggestionsEnabled = true
|
||||
var suggestions: [SuggestionItem] = []
|
||||
}
|
||||
|
||||
convenience init(configuration: CompletionSuggestionServiceMockConfiguration) {
|
||||
self.init()
|
||||
underlyingAreSuggestionsEnabled = configuration.areSuggestionsEnabled
|
||||
underlyingSuggestionsPublisher = Just(configuration.suggestions).eraseToAnyPublisher()
|
||||
}
|
||||
}
|
||||
|
@ -67,7 +67,6 @@ enum ComposerToolbarViewAction {
|
||||
struct ComposerToolbarViewState: BindableState {
|
||||
var composerMode: RoomScreenComposerMode = .default
|
||||
var composerEmpty = true
|
||||
var areSuggestionsEnabled = true
|
||||
var suggestions: [SuggestionItem] = []
|
||||
var audioPlayerState: AudioPlayerState
|
||||
var audioRecorderState: AudioRecorderState
|
||||
|
@ -45,8 +45,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
||||
self.completionSuggestionService = completionSuggestionService
|
||||
self.appSettings = appSettings
|
||||
|
||||
super.init(initialViewState: ComposerToolbarViewState(areSuggestionsEnabled: completionSuggestionService.areSuggestionsEnabled,
|
||||
audioPlayerState: .init(id: .recorderPreview, duration: 0),
|
||||
super.init(initialViewState: ComposerToolbarViewState(audioPlayerState: .init(id: .recorderPreview, duration: 0),
|
||||
audioRecorderState: .init(),
|
||||
bindings: .init()),
|
||||
imageProvider: mediaProvider)
|
||||
@ -89,9 +88,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
||||
.weakAssign(to: \.state.suggestions, on: self)
|
||||
.store(in: &cancellables)
|
||||
|
||||
if appSettings.mentionsEnabled {
|
||||
setupMentionsHandling(mentionDisplayHelper: mentionDisplayHelper)
|
||||
}
|
||||
setupMentionsHandling(mentionDisplayHelper: mentionDisplayHelper)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@ -190,7 +187,7 @@ final class ComposerToolbarViewModel: ComposerToolbarViewModelType, ComposerTool
|
||||
private func setupMentionsHandling(mentionDisplayHelper: MentionDisplayHelper) {
|
||||
wysiwygViewModel.textView.mentionDisplayHelper = mentionDisplayHelper
|
||||
|
||||
let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: appSettings.mentionsEnabled))
|
||||
let attributedStringBuilder = AttributedStringBuilder(cacheKey: "Composer", permalinkBaseURL: appSettings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
||||
|
||||
wysiwygViewModel.mentionReplacer = ComposerMentionReplacer { urlString, string in
|
||||
let attributedString: NSMutableAttributedString
|
||||
|
@ -19,6 +19,7 @@ import SwiftUI
|
||||
struct CompletionSuggestionView: View {
|
||||
let imageProvider: ImageProviderProtocol?
|
||||
let items: [SuggestionItem]
|
||||
var showBackgroundShadow = true
|
||||
let onTap: (SuggestionItem) -> Void
|
||||
|
||||
private enum Constants {
|
||||
@ -27,12 +28,12 @@ struct CompletionSuggestionView: View {
|
||||
// added by the list itself when presenting the divider
|
||||
static let listItemSpacing: CGFloat = 4.0
|
||||
static let leadingPadding: CGFloat = 16.0
|
||||
static let maxVisibleRows = 4
|
||||
// To make the scrolling more apparent we show a factional amount
|
||||
static let maxVisibleRows: CGFloat = 4.5
|
||||
}
|
||||
|
||||
// MARK: Public
|
||||
|
||||
var showBackgroundShadow = true
|
||||
@State private var prototypeListItemFrame: CGRect = .zero
|
||||
|
||||
var body: some View {
|
||||
@ -68,13 +69,12 @@ struct CompletionSuggestionView: View {
|
||||
.listRowInsets(.init(top: 0, leading: Constants.leadingPadding, bottom: 0, trailing: 0))
|
||||
}
|
||||
.listStyle(PlainListStyle())
|
||||
.frame(height: min(contentHeightForRowCount(Constants.maxVisibleRows),
|
||||
contentHeightForRowCount(items.count)))
|
||||
.frame(height: contentHeightForRowCount(min(CGFloat(items.count), Constants.maxVisibleRows)))
|
||||
.background(Color.compound.bgCanvasDefault)
|
||||
}
|
||||
|
||||
private func contentHeightForRowCount(_ count: Int) -> CGFloat {
|
||||
(prototypeListItemFrame.height + Constants.listItemPadding * 2 + Constants.listItemSpacing) * CGFloat(count) - Constants.listItemSpacing / 2 + Constants.topPadding - Constants.listItemPadding
|
||||
private func contentHeightForRowCount(_ count: CGFloat) -> CGFloat {
|
||||
(prototypeListItemFrame.height + Constants.listItemPadding * 2 + Constants.listItemSpacing) * count - Constants.listItemSpacing / 2 + Constants.topPadding - Constants.listItemPadding
|
||||
}
|
||||
|
||||
private struct ListItemPaddingModifier: ViewModifier {
|
||||
|
@ -38,12 +38,19 @@ struct ComposerToolbar: View {
|
||||
private let voiceMessageTooltipDuration = 1.0
|
||||
|
||||
@State private var frame: CGRect = .zero
|
||||
@Environment(\.verticalSizeClass) private var verticalSizeClass
|
||||
|
||||
var body: some View {
|
||||
VStack(spacing: 8) {
|
||||
topBar
|
||||
|
||||
if context.composerActionsEnabled {
|
||||
if verticalSizeClass != .compact,
|
||||
context.composerExpanded {
|
||||
suggestionView
|
||||
.padding(.leading, -5)
|
||||
.padding(.trailing, -8)
|
||||
}
|
||||
bottomBar
|
||||
}
|
||||
}
|
||||
@ -53,7 +60,7 @@ struct ComposerToolbar: View {
|
||||
ViewFrameReader(frame: $frame)
|
||||
}
|
||||
.overlay(alignment: .bottom) {
|
||||
if context.viewState.areSuggestionsEnabled {
|
||||
if verticalSizeClass != .compact, !context.composerExpanded {
|
||||
suggestionView
|
||||
.offset(y: -frame.height)
|
||||
}
|
||||
@ -68,7 +75,9 @@ struct ComposerToolbar: View {
|
||||
}
|
||||
|
||||
private var suggestionView: some View {
|
||||
CompletionSuggestionView(imageProvider: context.imageProvider, items: context.viewState.suggestions) { suggestion in
|
||||
CompletionSuggestionView(imageProvider: context.imageProvider,
|
||||
items: context.viewState.suggestions,
|
||||
showBackgroundShadow: !context.composerExpanded) { suggestion in
|
||||
context.send(viewAction: .selectedSuggestion(suggestion))
|
||||
}
|
||||
}
|
||||
|
@ -62,13 +62,19 @@ struct MessageComposer: View {
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
|
||||
@State private var composerFrame = CGRect.zero
|
||||
|
||||
private var mainContent: some View {
|
||||
VStack(alignment: .leading, spacing: -6) {
|
||||
header
|
||||
|
||||
composerView
|
||||
.frame(minHeight: composerHeight, alignment: .top)
|
||||
Color.clear
|
||||
.overlay(alignment: .top) {
|
||||
composerView
|
||||
.background(ViewFrameReader(frame: $composerFrame))
|
||||
}
|
||||
.frame(minHeight: ComposerConstant.minHeight, maxHeight: max(composerHeight, composerFrame.height),
|
||||
alignment: .top)
|
||||
.tint(.compound.iconAccentTertiary)
|
||||
.padding(.vertical, 10)
|
||||
.focused($focused)
|
||||
|
@ -339,7 +339,7 @@ struct HomeScreen_Previews: PreviewProvider, TestablePreview {
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled)),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
@ -155,7 +155,7 @@ struct HomeScreenEmptyStateView_Previews: PreviewProvider, TestablePreview {
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
|
||||
return HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled)),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
@ -190,7 +190,7 @@ struct HomeScreenRoomCell_Previews: PreviewProvider, TestablePreview {
|
||||
|
||||
let viewModel = HomeScreenViewModel(userSession: userSession,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled)),
|
||||
mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
@ -201,7 +201,7 @@ struct FormattedBodyText_Previews: PreviewProvider, TestablePreview {
|
||||
"<p>This is a list</p>\n<ul>\n<li>One</li>\n<li>Two</li>\n<li>And number 3</li>\n</ul>\n"
|
||||
]
|
||||
|
||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled))
|
||||
let attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
||||
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 24.0) {
|
||||
|
@ -49,7 +49,6 @@ protocol DeveloperOptionsProtocol: AnyObject {
|
||||
var userSuggestionsEnabled: Bool { get set }
|
||||
var readReceiptsEnabled: Bool { get set }
|
||||
var swiftUITimelineEnabled: Bool { get set }
|
||||
var mentionsEnabled: Bool { get set }
|
||||
var appLockFlowEnabled: Bool { get set }
|
||||
var elementCallEnabled: Bool { get set }
|
||||
var chatBackupEnabled: Bool { get set }
|
||||
|
@ -58,11 +58,6 @@ struct DeveloperOptionsScreen: View {
|
||||
Text("Resets on reboot")
|
||||
}
|
||||
|
||||
Toggle(isOn: $context.mentionsEnabled) {
|
||||
Text("Show user mentions")
|
||||
Text("Requires app reboot")
|
||||
}
|
||||
|
||||
Toggle(isOn: $context.elementCallEnabled) {
|
||||
Text("Element Call")
|
||||
}
|
||||
|
@ -98,7 +98,7 @@ enum RoomTimelineItemFixtures {
|
||||
sender: .init(id: "", displayName: "Helena"),
|
||||
content: .init(body: "",
|
||||
formattedBody: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL,
|
||||
mentionBuilder: MentionBuilder(mentionsEnabled: ServiceLocator.shared.settings.mentionsEnabled))
|
||||
mentionBuilder: MentionBuilder())
|
||||
.fromHTML("Hol' up <blockquote>New home office set up!</blockquote>That's amazing! Congrats 🥳")))
|
||||
]
|
||||
|
||||
|
@ -176,7 +176,7 @@ class MockScreen: Identifiable {
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock())
|
||||
let coordinator = HomeScreenCoordinator(parameters: .init(userSession: session,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true)),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
bugReportService: BugReportServiceMock(),
|
||||
navigationStackCoordinator: navigationStackCoordinator,
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher()))
|
||||
|
@ -19,7 +19,7 @@ import XCTest
|
||||
|
||||
class AttributedStringBuilderTests: XCTestCase {
|
||||
private let permalinkBaseURL = ServiceLocator.shared.settings.permalinkBaseURL
|
||||
private lazy var attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true))
|
||||
private lazy var attributedStringBuilder = AttributedStringBuilder(permalinkBaseURL: permalinkBaseURL, mentionBuilder: MentionBuilder())
|
||||
private let maxHeaderPointSize = ceil(UIFont.preferredFont(forTextStyle: .body).pointSize * 1.2)
|
||||
|
||||
func testRenderHTMLStringWithHeaders() {
|
||||
|
@ -21,7 +21,7 @@ class AttributedStringTests: XCTestCase {
|
||||
func testReplacingFontWithPresentationIntent() {
|
||||
// Given a string parsed from HTML that contains specific fixed size fonts.
|
||||
let boldString = "Bold"
|
||||
guard let originalString = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true))
|
||||
guard let originalString = AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder())
|
||||
.fromHTML("Normal <b>\(boldString)</b> Normal.") else {
|
||||
XCTFail("The attributed string should be built from the HTML.")
|
||||
return
|
||||
|
@ -30,7 +30,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
||||
let alice: RoomMemberProxyMock = .mockAlice
|
||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members))
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock, areSuggestionsEnabled: true)
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||
|
||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||
suggestions == []
|
||||
@ -67,7 +67,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
||||
let alice: RoomMemberProxyMock = .mockAlice
|
||||
let members: [RoomMemberProxyMock] = [alice, .mockBob, .mockCharlie, .mockMe]
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members, canUserTriggerRoomNotification: true))
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock, areSuggestionsEnabled: true)
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||
|
||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||
suggestions == []
|
||||
@ -93,7 +93,7 @@ final class CompletionSuggestionServiceTests: XCTestCase {
|
||||
let bob: RoomMemberProxyMock = .mockBob
|
||||
let members: [RoomMemberProxyMock] = [alice, bob, .mockMe]
|
||||
let roomProxyMock = RoomProxyMock(with: .init(displayName: "test", members: members, canUserTriggerRoomNotification: true))
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock, areSuggestionsEnabled: true)
|
||||
let service = CompletionSuggestionService(roomProxy: roomProxyMock)
|
||||
|
||||
var deferred = deferFulfillment(service.suggestionsPublisher) { suggestions in
|
||||
suggestions == []
|
||||
|
@ -31,7 +31,6 @@ class ComposerToolbarViewModelTests: XCTestCase {
|
||||
AppSettings.reset()
|
||||
appSettings = AppSettings()
|
||||
appSettings.richTextEditorEnabled = true
|
||||
appSettings.mentionsEnabled = true
|
||||
ServiceLocator.shared.register(appSettings: appSettings)
|
||||
wysiwygViewModel = WysiwygComposerViewModel()
|
||||
completionSuggestionServiceMock = CompletionSuggestionServiceMock(configuration: .init())
|
||||
|
@ -32,7 +32,7 @@ class HomeScreenViewModelTests: XCTestCase {
|
||||
viewModel = HomeScreenViewModel(userSession: MockUserSession(clientProxy: clientProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
voiceMessageMediaManager: VoiceMessageMediaManagerMock()),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder(mentionsEnabled: true)),
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: ServiceLocator.shared.settings.permalinkBaseURL, mentionBuilder: MentionBuilder()),
|
||||
selectedRoomPublisher: CurrentValueSubject<String?, Never>(nil).asCurrentValuePublisher(),
|
||||
appSettings: ServiceLocator.shared.settings,
|
||||
analytics: ServiceLocator.shared.analytics,
|
||||
|
BIN
UnitTests/__Snapshots__/PreviewTests/test_completionSuggestion.2.png
(Stored with Git LFS)
BIN
UnitTests/__Snapshots__/PreviewTests/test_completionSuggestion.2.png
(Stored with Git LFS)
Binary file not shown.
1
changelog.d/pr-1971.feature
Normal file
1
changelog.d/pr-1971.feature
Normal file
@ -0,0 +1 @@
|
||||
Pills for user mentions and the completion suggestion view are now enabled.
|
Loading…
x
Reference in New Issue
Block a user