mirror of
https://github.com/Novaloop-AG/element-x-ios.git
synced 2026-11-04 01:20:12 +00:00
Detect links in room detail topics and make it more obvious when the text is truncated (#2213)
This commit is contained in:
@@ -23,6 +23,7 @@ struct RoomDetailsScreenCoordinatorParameters {
|
||||
let mediaProvider: MediaProviderProtocol
|
||||
let userIndicatorController: UserIndicatorControllerProtocol
|
||||
let notificationSettings: NotificationSettingsProxyProtocol
|
||||
let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
}
|
||||
|
||||
enum RoomDetailsScreenCoordinatorAction {
|
||||
@@ -51,7 +52,8 @@ final class RoomDetailsScreenCoordinator: CoordinatorProtocol {
|
||||
roomProxy: parameters.roomProxy,
|
||||
mediaProvider: parameters.mediaProvider,
|
||||
userIndicatorController: parameters.userIndicatorController,
|
||||
notificationSettingsProxy: parameters.notificationSettings)
|
||||
notificationSettingsProxy: parameters.notificationSettings,
|
||||
attributedStringBuilder: parameters.attributedStringBuilder)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
|
||||
@@ -39,7 +39,8 @@ struct RoomDetailsScreenViewState: BindableState {
|
||||
let permalink: URL?
|
||||
|
||||
var title = ""
|
||||
var topic: String?
|
||||
var topic: AttributedString?
|
||||
var topicSummary: AttributedString?
|
||||
var avatarURL: URL?
|
||||
var joinedMembersCount: Int
|
||||
var isProcessingIgnoreRequest = false
|
||||
|
||||
@@ -25,6 +25,7 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
private let mediaProvider: MediaProviderProtocol
|
||||
private let userIndicatorController: UserIndicatorControllerProtocol
|
||||
private let notificationSettingsProxy: NotificationSettingsProxyProtocol
|
||||
private let attributedStringBuilder: AttributedStringBuilderProtocol
|
||||
|
||||
private var accountOwner: RoomMemberProxyProtocol? {
|
||||
didSet { updatePowerLevelPermissions() }
|
||||
@@ -42,12 +43,16 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
roomProxy: RoomProxyProtocol,
|
||||
mediaProvider: MediaProviderProtocol,
|
||||
userIndicatorController: UserIndicatorControllerProtocol,
|
||||
notificationSettingsProxy: NotificationSettingsProxyProtocol) {
|
||||
notificationSettingsProxy: NotificationSettingsProxyProtocol,
|
||||
attributedStringBuilder: AttributedStringBuilderProtocol) {
|
||||
self.accountUserID = accountUserID
|
||||
self.roomProxy = roomProxy
|
||||
self.mediaProvider = mediaProvider
|
||||
self.userIndicatorController = userIndicatorController
|
||||
self.notificationSettingsProxy = notificationSettingsProxy
|
||||
self.attributedStringBuilder = attributedStringBuilder
|
||||
|
||||
let topic = attributedStringBuilder.fromPlain(roomProxy.topic)
|
||||
|
||||
super.init(initialViewState: .init(roomId: roomProxy.id,
|
||||
canonicalAlias: roomProxy.canonicalAlias,
|
||||
@@ -55,7 +60,8 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
isDirect: roomProxy.isDirect,
|
||||
permalink: roomProxy.permalink,
|
||||
title: roomProxy.roomTitle,
|
||||
topic: roomProxy.topic,
|
||||
topic: topic,
|
||||
topicSummary: topic?.unattributedStringByReplacingNewlinesWithSpaces(),
|
||||
avatarURL: roomProxy.avatarURL,
|
||||
joinedMembersCount: roomProxy.joinedMembersCount,
|
||||
notificationSettingsState: .loading,
|
||||
@@ -126,7 +132,10 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
.sink { [weak self] _ in
|
||||
guard let self else { return }
|
||||
self.state.title = self.roomProxy.roomTitle
|
||||
self.state.topic = self.roomProxy.topic
|
||||
|
||||
let topic = attributedStringBuilder.fromPlain(self.roomProxy.topic)
|
||||
self.state.topic = topic
|
||||
self.state.topicSummary = topic?.unattributedStringByReplacingNewlinesWithSpaces()
|
||||
self.state.avatarURL = self.roomProxy.avatarURL
|
||||
self.state.joinedMembersCount = self.roomProxy.joinedMembersCount
|
||||
}
|
||||
@@ -299,3 +308,10 @@ class RoomDetailsScreenViewModel: RoomDetailsScreenViewModelType, RoomDetailsScr
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private extension AttributedString {
|
||||
/// Returns a new string without attributes and in which newlines are replaced with spaces
|
||||
func unattributedStringByReplacingNewlinesWithSpaces() -> AttributedString {
|
||||
AttributedString(characters.map { $0.isNewline ? " " : $0 })
|
||||
}
|
||||
}
|
||||
|
||||
@@ -123,10 +123,19 @@ struct RoomDetailsScreen: View {
|
||||
private var topicSection: some View {
|
||||
if context.viewState.hasTopicSection {
|
||||
Section {
|
||||
if let topic = context.viewState.topic, !topic.isEmpty {
|
||||
ListRow(label: .description(topic), kind: .label)
|
||||
.lineLimit(isTopicExpanded ? nil : 3)
|
||||
.onTapGesture { isTopicExpanded.toggle() }
|
||||
if let topic = context.viewState.topic, !topic.characters.isEmpty, let topicSummary = context.viewState.topicSummary {
|
||||
ListRow(kind: .custom {
|
||||
Text(isTopicExpanded ? topic : topicSummary)
|
||||
.font(.compound.bodySM)
|
||||
.foregroundColor(.compound.textSecondary)
|
||||
.lineLimit(isTopicExpanded ? nil : 3)
|
||||
.accentColor(.compound.textLinkExternal)
|
||||
.padding(ListRowPadding.insets)
|
||||
.textSelection(.enabled)
|
||||
})
|
||||
.onTapGesture {
|
||||
isTopicExpanded.toggle()
|
||||
}
|
||||
} else {
|
||||
ListRow(label: .plain(title: L10n.screenRoomDetailsAddTopicTitle),
|
||||
kind: .button { context.send(viewAction: .processTapAddTopic) })
|
||||
@@ -264,7 +273,14 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
.mockCharlie
|
||||
]
|
||||
let roomProxy = RoomProxyMock(with: .init(id: "room_a_id", displayName: "Room A",
|
||||
topic: "Bacon ipsum dolor amet short ribs buffalo pork loin cupim frankfurter. Burgdoggen pig shankle biltong flank ham jowl sirloin bacon cow. T-bone alcatra boudin beef spare ribs pig fatback jerky swine short ribs shankle chislic frankfurter pork loin. Chicken tri-tip bresaola t-bone pastrami brisket.", // swiftlint:disable:this line_length
|
||||
topic: """
|
||||
Discussions about Element X iOS | https://github.com/vector-im/element-x-ios
|
||||
|
||||
Feature Status: https://github.com/vector-im/element-x-ios/issues/1225
|
||||
|
||||
App Store: https://apple.co/3r6LJHZ
|
||||
TestFlight: https://testflight.apple.com/join/uZbeZCOi
|
||||
""",
|
||||
isDirect: false,
|
||||
isEncrypted: true,
|
||||
canonicalAlias: "#alias:domain.com",
|
||||
@@ -279,7 +295,9 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
roomProxy: roomProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
notificationSettingsProxy: notificationSettingsProxy)
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
||||
mentionBuilder: MentionBuilder()))
|
||||
}()
|
||||
|
||||
static let dmRoomViewModel = {
|
||||
@@ -302,7 +320,9 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
roomProxy: roomProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
notificationSettingsProxy: notificationSettingsProxy)
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
||||
mentionBuilder: MentionBuilder()))
|
||||
}()
|
||||
|
||||
static let simpleRoomViewModel = {
|
||||
@@ -322,7 +342,9 @@ struct RoomDetailsScreen_Previews: PreviewProvider, TestablePreview {
|
||||
roomProxy: roomProxy,
|
||||
mediaProvider: MockMediaProvider(),
|
||||
userIndicatorController: ServiceLocator.shared.userIndicatorController,
|
||||
notificationSettingsProxy: notificationSettingsProxy)
|
||||
notificationSettingsProxy: notificationSettingsProxy,
|
||||
attributedStringBuilder: AttributedStringBuilder(permalinkBaseURL: .userDirectory,
|
||||
mentionBuilder: MentionBuilder()))
|
||||
}()
|
||||
|
||||
static var previews: some View {
|
||||
|
||||
Reference in New Issue
Block a user