reply view will now render as plain pills

instead of rendering nothing
This commit is contained in:
Mauro Romito
2025-03-25 12:30:57 +01:00
committed by Mauro
parent dbb59a4012
commit 791ce67808
7 changed files with 100 additions and 21 deletions
@@ -117,6 +117,12 @@ struct TimelineViewState: BindableState {
/// A closure that updates the associated pill context /// A closure that updates the associated pill context
var pillContextUpdater: (@MainActor (PillContext) -> Void)? var pillContextUpdater: (@MainActor (PillContext) -> Void)?
/// A closure that returns the associated room name give its id
var roomNameForIDResolver: (@MainActor (String) -> String?)?
/// A closure that returns the associated room name give its alias
var roomNameForAliasResolver: (@MainActor (String) -> String?)?
var emojiProvider: EmojiProviderProtocol var emojiProvider: EmojiProviderProtocol
} }
@@ -121,6 +121,14 @@ class TimelineViewModel: TimelineViewModelType, TimelineViewModelProtocol {
self?.pillContextUpdater(pillContext) self?.pillContextUpdater(pillContext)
} }
state.roomNameForIDResolver = { [weak self] roomID in
self?.clientProxy.roomSummaryForIdentifier(roomID)?.name
}
state.roomNameForAliasResolver = { [weak self] alias in
self?.clientProxy.roomSummaryForAlias(alias)?.name
}
state.timelineState.paginationState = timelineController.paginationState state.timelineState.paginationState = timelineController.paginationState
buildTimelineViews(timelineItems: timelineController.timelineItems) buildTimelineViews(timelineItems: timelineController.timelineItems)
@@ -935,19 +943,22 @@ extension TimelineViewModel {
static let mock = mock(timelineKind: .live) static let mock = mock(timelineKind: .live)
static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil) -> TimelineViewModel { static func mock(timelineKind: TimelineKind = .live, timelineController: MockTimelineController? = nil) -> TimelineViewModel {
TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")), let clientProxyMock = ClientProxyMock(.init())
focussedEventID: nil, clientProxyMock.roomSummaryForAliasReturnValue = .mock(id: "!room:matrix.org", name: "Room")
timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind), clientProxyMock.roomSummaryForIdentifierReturnValue = .mock(id: "!room:matrix.org", name: "Room", canonicalAlias: "#room:matrix.org")
mediaProvider: MediaProviderMock(configuration: .init()), return TimelineViewModel(roomProxy: JoinedRoomProxyMock(.init(name: "Preview room")),
mediaPlayerProvider: MediaPlayerProviderMock(), focussedEventID: nil,
voiceMessageMediaManager: VoiceMessageMediaManagerMock(), timelineController: timelineController ?? MockTimelineController(timelineKind: timelineKind),
userIndicatorController: ServiceLocator.shared.userIndicatorController, mediaProvider: MediaProviderMock(configuration: .init()),
appMediator: AppMediatorMock.default, mediaPlayerProvider: MediaPlayerProviderMock(),
appSettings: ServiceLocator.shared.settings, voiceMessageMediaManager: VoiceMessageMediaManagerMock(),
analyticsService: ServiceLocator.shared.analytics, userIndicatorController: ServiceLocator.shared.userIndicatorController,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings), appMediator: AppMediatorMock.default,
timelineControllerFactory: TimelineControllerFactoryMock(.init()), appSettings: ServiceLocator.shared.settings,
clientProxy: ClientProxyMock(.init())) analyticsService: ServiceLocator.shared.analytics,
emojiProvider: EmojiProvider(appSettings: ServiceLocator.shared.settings),
timelineControllerFactory: TimelineControllerFactoryMock(.init()),
clientProxy: clientProxyMock)
} }
} }
@@ -200,6 +200,28 @@ struct TimelineReplyView: View {
if attributes[.MatrixAllUsersMention] as? Bool == true { if attributes[.MatrixAllUsersMention] as? Bool == true {
attributedString.replaceCharacters(in: range, with: PillUtilities.atRoom) attributedString.replaceCharacters(in: range, with: PillUtilities.atRoom)
} }
if let roomAlias = attributes[.MatrixRoomAlias] as? String {
let roomName = context.viewState.roomNameForAliasResolver?(roomAlias)
attributedString.replaceCharacters(in: range, with: PillUtilities.roomPillDisplayText(roomName: roomName, rawRoomText: roomAlias))
}
if let roomID = attributes[.MatrixRoomID] as? String {
let roomName = context.viewState.roomNameForIDResolver?(roomID)
attributedString.replaceCharacters(in: range, with: PillUtilities.roomPillDisplayText(roomName: roomName, rawRoomText: roomID))
}
if let eventOnRoomID = attributes[.MatrixEventOnRoomID] as? EventOnRoomIDAttribute.Value {
let roomID = eventOnRoomID.roomID
let roomName = context.viewState.roomNameForIDResolver?(roomID)
attributedString.replaceCharacters(in: range, with: PillUtilities.eventPillDisplayText(roomName: roomName, rawRoomText: roomID))
}
if let eventOnRoomAlias = attributes[.MatrixEventOnRoomAlias] as? EventOnRoomAliasAttribute.Value {
let roomAlias = eventOnRoomAlias.alias
let roomName = context.viewState.roomNameForAliasResolver?(roomAlias)
attributedString.replaceCharacters(in: range, with: PillUtilities.eventPillDisplayText(roomName: roomName, rawRoomText: eventOnRoomAlias.alias))
}
} }
return attributedString.string return attributedString.string
} }
@@ -221,6 +243,30 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
return attributedString return attributedString
}() }()
static let attributedStringWithRoomAliasMention = {
var attributedString = AttributedString("to be replaced")
attributedString.roomAlias = "#room:matrix.org"
return attributedString
}()
static let attributedStringWithRoomIDMention = {
var attributedString = AttributedString("to be replaced")
attributedString.roomID = "!room:matrix.org"
return attributedString
}()
static let attributedStringWithEventOnRoomIDMention = {
var attributedString = AttributedString("to be replaced")
attributedString.eventOnRoomID = .init(roomID: "!room:matrix.org", eventID: "$event")
return attributedString
}()
static let attributedStringWithEventOnRoomAliasMention = {
var attributedString = AttributedString("to be replaced")
attributedString.eventOnRoomAlias = .init(alias: "#room:matrix.org", eventID: "$event")
return attributedString
}()
static var previewItems: [TimelineReplyView] { static var previewItems: [TimelineReplyView] {
[ [
TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .notLoaded(eventID: "")), TimelineReplyView(placement: .timeline, timelineItemReplyDetails: .notLoaded(eventID: "")),
@@ -301,6 +347,22 @@ struct TimelineReplyView_Previews: PreviewProvider, TestablePreview {
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"), timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123", eventID: "123",
eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithAtRoomMention))))), eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithAtRoomMention))))),
TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123",
eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithRoomAliasMention))))),
TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123",
eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithRoomIDMention))))),
TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123",
eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithEventOnRoomIDMention))))),
TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123",
eventContent: .message(.notice(.init(body: "", formattedBody: attributedStringWithEventOnRoomAliasMention))))),
TimelineReplyView(placement: .timeline, TimelineReplyView(placement: .timeline,
timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"), timelineItemReplyDetails: .loaded(sender: .init(id: "", displayName: "Bob"),
eventID: "123", eventID: "123",
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:c20e70f0286b2d7a861d740ff4162d8bb07c2e9ca57cfb3abf997e1ab87e7017 oid sha256:3b9ef6de65b855b786c3973dd2d19b98500b42288f0fa0ad270fff58cbb2b87b
size 172541 size 211786
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:df9e3d57833f3d14ff6521a4946164479a52afb20607cca016dbc51b20fe9439 oid sha256:1f2f9509ad4173efbc5d31cd36e2090c4ef265556b512ba581d50bc419eef667
size 180282 size 219356
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:7b9fe17381b6d9ee105861a76d50b7c1a78ffaf29fa03cad5c64ff9853a25b01 oid sha256:c5a3d15cb45d333c8262de10a8503b418b0df28b37922f569e5b5a1e67132450
size 122809 size 148474
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1 version https://git-lfs.github.com/spec/v1
oid sha256:911c2bbff4bb91991cc9cc2509fd49442626077a188459a67b2ce35263270c0c oid sha256:8bfb5dce96a9bab1b0bf4ade63aaeecc90879618e29f7f23defa63e0be473957
size 128295 size 153708