mirror of
https://gitlab.opencode.de/bwi/bundesmessenger/clients/bundesmessenger-ios.git
synced 2026-04-25 11:02:48 +02:00
Load and store URLPreviewViewData in RoomBubbleCellData.
Implement close button and store the action in Core Data. Hide the preview image view when no image is received. Remove line breaks in description text.
This commit is contained in:
@@ -21,36 +21,49 @@ import Reusable
|
||||
class URLPreviewView: UIView, NibLoadable, Themable {
|
||||
// MARK: - Constants
|
||||
|
||||
private enum Constants { }
|
||||
private static let sizingView = URLPreviewView.instantiate()
|
||||
|
||||
private enum Constants {
|
||||
// URL Previews
|
||||
|
||||
static let maxHeight: CGFloat = 247.0
|
||||
static let width: CGFloat = 267.0
|
||||
}
|
||||
|
||||
// MARK: - Properties
|
||||
|
||||
var viewModel: URLPreviewViewModel! {
|
||||
var preview: URLPreviewViewData? {
|
||||
didSet {
|
||||
viewModel.viewDelegate = self
|
||||
guard let preview = preview else { return }
|
||||
renderLoaded(preview)
|
||||
}
|
||||
}
|
||||
|
||||
weak var delegate: URLPreviewViewDelegate?
|
||||
|
||||
@IBOutlet weak var imageContainer: UIView!
|
||||
@IBOutlet weak var imageView: UIImageView!
|
||||
@IBOutlet weak var faviconImageView: UIImageView!
|
||||
@IBOutlet weak var closeButton: UIButton!
|
||||
|
||||
@IBOutlet weak var siteNameLabel: UILabel!
|
||||
@IBOutlet weak var titleLabel: UILabel!
|
||||
@IBOutlet weak var descriptionLabel: UILabel!
|
||||
|
||||
/// The constraint that pins the top of the text container to the top of the view.
|
||||
@IBOutlet weak var textContainerViewConstraint: NSLayoutConstraint!
|
||||
/// The constraint that pins the top of the text container to the bottom of the image container.
|
||||
@IBOutlet weak var textContainerImageConstraint: NSLayoutConstraint!
|
||||
|
||||
override var intrinsicContentSize: CGSize {
|
||||
CGSize(width: RoomBubbleCellLayout.urlPreviewViewWidth, height: RoomBubbleCellLayout.urlPreviewViewHeight)
|
||||
CGSize(width: Constants.width, height: Constants.maxHeight)
|
||||
}
|
||||
|
||||
// MARK: - Setup
|
||||
|
||||
static func instantiate(viewModel: URLPreviewViewModel) -> Self {
|
||||
static func instantiate() -> Self {
|
||||
let view = Self.loadFromNib()
|
||||
view.update(theme: ThemeService.shared().theme)
|
||||
|
||||
view.viewModel = viewModel
|
||||
viewModel.process(viewAction: .loadData)
|
||||
|
||||
return view
|
||||
}
|
||||
|
||||
@@ -63,14 +76,10 @@ class URLPreviewView: UIView, NibLoadable, Themable {
|
||||
layer.masksToBounds = true
|
||||
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
faviconImageView.layer.cornerRadius = 6
|
||||
|
||||
siteNameLabel.isUserInteractionEnabled = false
|
||||
titleLabel.isUserInteractionEnabled = false
|
||||
descriptionLabel.isUserInteractionEnabled = false
|
||||
|
||||
#warning("Debugging for previews - to be removed")
|
||||
faviconImageView.backgroundColor = .systemBlue.withAlphaComponent(0.7)
|
||||
}
|
||||
|
||||
// MARK: - Public
|
||||
@@ -86,9 +95,19 @@ class URLPreviewView: UIView, NibLoadable, Themable {
|
||||
|
||||
descriptionLabel.textColor = theme.colors.secondaryContent
|
||||
descriptionLabel.font = theme.fonts.caption1
|
||||
|
||||
let closeButtonAsset = ThemeService.shared().isCurrentThemeDark() ? Asset.Images.urlPreviewCloseDark : Asset.Images.urlPreviewClose
|
||||
closeButton.setImage(closeButtonAsset.image, for: .normal)
|
||||
}
|
||||
|
||||
static func contentViewHeight(for preview: URLPreviewViewData) -> CGFloat {
|
||||
sizingView.renderLoaded(preview)
|
||||
|
||||
return sizingView.systemLayoutSizeFitting(sizingView.intrinsicContentSize).height
|
||||
}
|
||||
|
||||
// MARK: - Private
|
||||
#warning("Check whether we should show a loading state.")
|
||||
private func renderLoading(_ url: URL) {
|
||||
imageView.image = nil
|
||||
|
||||
@@ -98,48 +117,49 @@ class URLPreviewView: UIView, NibLoadable, Themable {
|
||||
}
|
||||
|
||||
private func renderLoaded(_ preview: URLPreviewViewData) {
|
||||
imageView.image = preview.image
|
||||
if let image = preview.image {
|
||||
imageView.image = image
|
||||
showImageContainer()
|
||||
} else {
|
||||
imageView.image = nil
|
||||
hideImageContainer()
|
||||
}
|
||||
|
||||
siteNameLabel.text = preview.siteName ?? preview.url.host
|
||||
titleLabel.text = preview.title
|
||||
descriptionLabel.text = preview.text
|
||||
}
|
||||
|
||||
private func renderError(_ error: Error) {
|
||||
imageView.image = nil
|
||||
private func showImageContainer() {
|
||||
// When the image container has a superview it is already visible
|
||||
guard imageContainer.superview == nil else { return }
|
||||
|
||||
siteNameLabel.text = "Error"
|
||||
titleLabel.text = descriptionLabel.text
|
||||
descriptionLabel.text = error.localizedDescription
|
||||
textContainerViewConstraint.isActive = false
|
||||
addSubview(imageContainer)
|
||||
textContainerImageConstraint.isActive = true
|
||||
|
||||
// Ensure the close button remains visible
|
||||
bringSubviewToFront(closeButton)
|
||||
}
|
||||
|
||||
private func hideImageContainer() {
|
||||
textContainerImageConstraint.isActive = false
|
||||
imageContainer.removeFromSuperview()
|
||||
textContainerViewConstraint.isActive = true
|
||||
}
|
||||
|
||||
// MARK: - Action
|
||||
@IBAction private func openURL(_ sender: Any) {
|
||||
MXLog.debug("[URLPreviewView] Link was tapped.")
|
||||
viewModel.process(viewAction: .openURL)
|
||||
guard let preview = preview else { return }
|
||||
|
||||
// Ask the delegate to open the URL for the event, as the bubble component
|
||||
// has the original un-sanitized URL that needs to be opened.
|
||||
delegate?.didOpenURLFromPreviewView(self, for: preview.eventID, in: preview.roomID)
|
||||
}
|
||||
|
||||
@IBAction private func close(_ sender: Any) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// MARK: URLPreviewViewModelViewDelegate
|
||||
extension URLPreviewView: URLPreviewViewModelViewDelegate {
|
||||
func urlPreviewViewModel(_ viewModel: URLPreviewViewModelType, didUpdateViewState viewState: URLPreviewViewState) {
|
||||
DispatchQueue.main.async {
|
||||
switch viewState {
|
||||
case .loading(let url):
|
||||
self.renderLoading(url)
|
||||
case .loaded(let preview):
|
||||
self.renderLoaded(preview)
|
||||
case .error(let error):
|
||||
self.renderError(error)
|
||||
case .hidden:
|
||||
self.frame.size.height = 0
|
||||
}
|
||||
}
|
||||
guard let preview = preview else { return }
|
||||
delegate?.didCloseURLPreviewView(self, for: preview.eventID, in: preview.roomID)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user