Files
element-x-ios/ElementX/Sources/Screens/RoomScreen/View/RoomScreenFooterView.swift
T

99 lines
4.2 KiB
Swift

//
// Copyright 2024 New Vector Ltd.
//
// SPDX-License-Identifier: AGPL-3.0-only
// Please see LICENSE in the repository root for full details.
//
import SwiftUI
struct RoomScreenFooterView: View {
let details: RoomScreenFooterViewDetails?
let mediaProvider: MediaProviderProtocol?
let callback: (RoomScreenFooterViewAction) -> Void
var body: some View {
if let details {
ZStack(alignment: .top) {
VStack(spacing: 0) {
Color.compound.borderInfoSubtle
.frame(height: 1)
LinearGradient(colors: [.compound.bgInfoSubtle, .compound.bgCanvasDefault],
startPoint: .top,
endPoint: .bottom)
}
switch details {
case .pinViolation(let member, let learnMoreURL):
pinViolation(member: member, learnMoreURL: learnMoreURL)
}
}
.padding(.top, 8)
.fixedSize(horizontal: false, vertical: true)
}
}
private func pinViolation(member: RoomMemberProxyProtocol,
learnMoreURL: URL) -> some View {
VStack(spacing: 16) {
HStack(spacing: 16) {
LoadableAvatarImage(url: member.avatarURL,
name: member.disambiguatedDisplayName,
contentID: member.userID,
avatarSize: .user(on: .timeline),
mediaProvider: mediaProvider)
Text(pinViolationDescriptionWithLearnMoreLink(displayName: member.displayName,
userID: member.userID,
url: learnMoreURL))
.font(.compound.bodyMD)
.foregroundColor(.compound.textPrimary)
}
Button(L10n.actionOk) {
callback(.resolvePinViolation(userID: member.userID))
}
.buttonStyle(.compound(.primary, size: .medium))
}
.padding(.top, 16)
.padding(.horizontal, 16)
.padding(.bottom, 8)
}
private func pinViolationDescriptionWithLearnMoreLink(displayName: String?, userID: String, url: URL) -> AttributedString {
let userIDPlaceholder = "{mxid}"
let linkPlaceholder = "{link}"
let displayName = displayName ?? fallbackDisplayName(userID)
var description = AttributedString(L10n.cryptoIdentityChangePinViolationNew(displayName, userIDPlaceholder, linkPlaceholder))
var userIDString = AttributedString(L10n.cryptoIdentityChangePinViolationNewUserId(userID))
userIDString.bold()
description.replace(userIDPlaceholder, with: userIDString)
var linkString = AttributedString(L10n.actionLearnMore)
linkString.link = url
linkString.bold()
description.replace(linkPlaceholder, with: linkString)
return description
}
private func fallbackDisplayName(_ userID: String) -> String {
guard let localpart = userID.components(separatedBy: ":").first else { return userID }
return String(localpart.trimmingPrefix("@"))
}
}
struct RoomScreenFooterView_Previews: PreviewProvider, TestablePreview {
static let bobDetails: RoomScreenFooterViewDetails = .pinViolation(member: RoomMemberProxyMock.mockBob,
learnMoreURL: "https://element.io/")
static let noNameDetails: RoomScreenFooterViewDetails = .pinViolation(member: RoomMemberProxyMock.mockNoName,
learnMoreURL: "https://element.io/")
static var previews: some View {
RoomScreenFooterView(details: bobDetails, mediaProvider: MediaProviderMock(configuration: .init())) { _ in }
.previewDisplayName("With displayname")
RoomScreenFooterView(details: noNameDetails, mediaProvider: MediaProviderMock(configuration: .init())) { _ in }
.previewDisplayName("Without displayname")
}
}