feat: add sensitive hint label for status media

This commit is contained in:
CMK 2022-04-18 16:15:24 +08:00
parent c4ab4f68c6
commit 41e1b75c62
5 changed files with 61 additions and 100 deletions

View File

@ -129,6 +129,7 @@
"show_post": "Show Post",
"show_user_profile": "Show user profile",
"content_warning": "Content Warning",
"sensitive_content": "Sensitive Content",
"media_content_warning": "Tap anywhere to reveal",
"tap_to_reveal": "Tap to reveal",
"poll": {

View File

@ -39,6 +39,8 @@ final class NotificationTimelineViewController: UIViewController, NeedsDependenc
return tableView
}()
let cellFrameCache = NSCache<NSNumber, NSValue>()
deinit {
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
}
@ -122,6 +124,16 @@ extension NotificationTimelineViewController {
}
// MARK: - CellFrameCacheContainer
extension NotificationTimelineViewController: CellFrameCacheContainer {
func keyForCache(tableView: UITableView, indexPath: IndexPath) -> NSNumber? {
guard let diffableDataSource = viewModel.diffableDataSource else { return nil }
guard let item = diffableDataSource.itemIdentifier(for: indexPath) else { return nil }
let key = NSNumber(value: item.hashValue)
return key
}
}
extension NotificationTimelineViewController {
@objc private func refreshControlValueChanged(_ sender: UIRefreshControl) {
@ -162,6 +174,13 @@ extension NotificationTimelineViewController: UITableViewDelegate, AutoGenerateT
// sourcery:end
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
guard let frame = retrieveCellFrame(tableView: tableView, indexPath: indexPath) else {
return 300
}
return ceil(frame.height)
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
guard let item = viewModel.diffableDataSource?.itemIdentifier(for: indexPath) else {
return
@ -172,6 +191,10 @@ extension NotificationTimelineViewController: UITableViewDelegate, AutoGenerateT
await viewModel.loadMore(item: item)
}
}
func tableView(_ tableView: UITableView, didEndDisplaying cell: UITableViewCell, forRowAt indexPath: IndexPath) {
cacheCellFrame(tableView: tableView, didEndDisplaying: cell, forRowAt: indexPath)
}
}

View File

@ -48,22 +48,7 @@ public final class MediaGridContainerView: UIView {
return mediaViews
}()
// let sensitiveToggleButtonBlurVisualEffectView: UIVisualEffectView = {
// let visualEffectView = UIVisualEffectView(effect: ContentWarningOverlayView.blurVisualEffect)
// visualEffectView.layer.masksToBounds = true
// visualEffectView.layer.cornerRadius = MediaGridContainerView.sensitiveToggleButtonSize.width / 2
// visualEffectView.layer.cornerCurve = .continuous
// return visualEffectView
// }()
// let sensitiveToggleButtonVibrancyVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: ContentWarningOverlayView.blurVisualEffect))
// let sensitiveToggleButton: HitTestExpandedButton = {
// let button = HitTestExpandedButton(type: .system)
// button.contentEdgeInsets = UIEdgeInsets(top: 4, left: 4, bottom: 4, right: 4)
// button.imageView?.contentMode = .scaleAspectFit
// button.setImage(UIImage(systemName: "eye.slash.fill"), for: .normal)
// return button
// }()
let contentWarningOverlay = ContentWarningOverlayView()
public override init(frame: CGRect) {
super.init(frame: frame)
@ -86,7 +71,8 @@ public final class MediaGridContainerView: UIView {
extension MediaGridContainerView {
private func _init() {
// sensitiveToggleButton.addTarget(self, action: #selector(MediaGridContainerView.sensitiveToggleButtonDidPressed(_:)), for: .touchUpInside)
contentWarningOverlay.isUserInteractionEnabled = false
contentWarningOverlay.isHidden = true
}
}
@ -112,8 +98,8 @@ extension MediaGridContainerView {
let mediaView = _mediaViews[0]
layout.layout(in: self, mediaView: mediaView)
// layoutSensitiveToggleButton()
// bringSubviewToFront(sensitiveToggleButtonBlurVisualEffectView)
layoutContentWarningOverlay()
bringSubviewToFront(contentWarningOverlay)
return mediaView
}
@ -124,8 +110,8 @@ extension MediaGridContainerView {
let mediaViews = Array(_mediaViews[0..<layout.count])
layout.layout(in: self, mediaViews: mediaViews)
// layoutSensitiveToggleButton()
// bringSubviewToFront(sensitiveToggleButtonBlurVisualEffectView)
layoutContentWarningOverlay()
bringSubviewToFront(contentWarningOverlay)
return mediaViews
}
@ -147,34 +133,16 @@ extension MediaGridContainerView {
}
extension MediaGridContainerView {
// private func layoutSensitiveToggleButton() {
// sensitiveToggleButtonBlurVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
// addSubview(sensitiveToggleButtonBlurVisualEffectView)
// NSLayoutConstraint.activate([
// sensitiveToggleButtonBlurVisualEffectView.topAnchor.constraint(equalTo: topAnchor, constant: 16),
// trailingAnchor.constraint(equalTo: sensitiveToggleButtonBlurVisualEffectView.trailingAnchor, constant: 16),
// ])
//
// sensitiveToggleButtonVibrancyVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
// sensitiveToggleButtonBlurVisualEffectView.contentView.addSubview(sensitiveToggleButtonVibrancyVisualEffectView)
// NSLayoutConstraint.activate([
// sensitiveToggleButtonVibrancyVisualEffectView.topAnchor.constraint(equalTo: sensitiveToggleButtonBlurVisualEffectView.contentView.topAnchor),
// sensitiveToggleButtonVibrancyVisualEffectView.leadingAnchor.constraint(equalTo: sensitiveToggleButtonBlurVisualEffectView.contentView.leadingAnchor),
// sensitiveToggleButtonVibrancyVisualEffectView.trailingAnchor.constraint(equalTo: sensitiveToggleButtonBlurVisualEffectView.contentView.trailingAnchor),
// sensitiveToggleButtonVibrancyVisualEffectView.bottomAnchor.constraint(equalTo: sensitiveToggleButtonBlurVisualEffectView.contentView.bottomAnchor),
// ])
//
// sensitiveToggleButton.translatesAutoresizingMaskIntoConstraints = false
// sensitiveToggleButtonVibrancyVisualEffectView.contentView.addSubview(sensitiveToggleButton)
// NSLayoutConstraint.activate([
// sensitiveToggleButton.topAnchor.constraint(equalTo: sensitiveToggleButtonVibrancyVisualEffectView.contentView.topAnchor),
// sensitiveToggleButton.leadingAnchor.constraint(equalTo: sensitiveToggleButtonVibrancyVisualEffectView.contentView.leadingAnchor),
// sensitiveToggleButtonVibrancyVisualEffectView.contentView.trailingAnchor.constraint(equalTo: sensitiveToggleButton.trailingAnchor),
// sensitiveToggleButtonVibrancyVisualEffectView.contentView.bottomAnchor.constraint(equalTo: sensitiveToggleButton.bottomAnchor),
// sensitiveToggleButton.widthAnchor.constraint(equalToConstant: MediaGridContainerView.sensitiveToggleButtonSize.width).priority(.required - 1),
// sensitiveToggleButton.heightAnchor.constraint(equalToConstant: MediaGridContainerView.sensitiveToggleButtonSize.height).priority(.required - 1),
// ])
// }
private func layoutContentWarningOverlay() {
contentWarningOverlay.translatesAutoresizingMaskIntoConstraints = false
addSubview(contentWarningOverlay)
NSLayoutConstraint.activate([
contentWarningOverlay.topAnchor.constraint(equalTo: topAnchor),
contentWarningOverlay.leadingAnchor.constraint(equalTo: leadingAnchor),
contentWarningOverlay.trailingAnchor.constraint(equalTo: trailingAnchor),
contentWarningOverlay.bottomAnchor.constraint(equalTo: bottomAnchor),
])
}
}
extension MediaGridContainerView {

View File

@ -385,6 +385,7 @@ extension StatusView.ViewModel {
$isMediaReveal
.sink { isMediaReveal in
statusView.mediaGridContainerView.contentWarningOverlay.isHidden = isMediaReveal
statusView.mediaGridContainerView.viewModel.isSensitiveToggleButtonDisplay = isMediaReveal
}
.store(in: &disposeBag)

View File

@ -7,28 +7,24 @@
import os.log
import UIKit
public protocol ContentWarningOverlayViewDelegate: AnyObject {
func contentWarningOverlayViewDidPressed(_ contentWarningOverlayView: ContentWarningOverlayView)
}
import MastodonLocalization
public final class ContentWarningOverlayView: UIView {
public static let blurVisualEffect = UIBlurEffect(style: .systemUltraThinMaterial)
let logger = Logger(subsystem: "ContentWarningOverlayView", category: "View")
public weak var delegate: ContentWarningOverlayViewDelegate?
public let blurVisualEffectView = UIVisualEffectView(effect: ContentWarningOverlayView.blurVisualEffect)
public let vibrancyVisualEffectView = UIVisualEffectView(effect: UIVibrancyEffect(blurEffect: ContentWarningOverlayView.blurVisualEffect))
// let alertImageView: UIImageView = {
// let imageView = UIImageView()
// imageView.image = Asset.Indices.exclamationmarkTriangleLarge.image.withRenderingMode(.alwaysTemplate)
// return imageView
// }()
public let tapGestureRecognizer = UITapGestureRecognizer.singleTapGestureRecognizer
let hintLabel: UILabel = {
let label = UILabel()
label.font = .systemFont(ofSize: 18, weight: .regular)
label.text = L10n.Common.Controls.Status.tapToReveal
label.textAlignment = .center
label.textColor = .white.withAlphaComponent(0.7)
label.layer.shadowOpacity = 0.3
label.layer.shadowOffset = CGSize(width: 0, height: 2)
label.layer.shadowRadius = 2
label.layer.shadowColor = UIColor.black.cgColor
return label
}()
override init(frame: CGRect) {
super.init(frame: frame)
@ -44,40 +40,12 @@ public final class ContentWarningOverlayView: UIView {
extension ContentWarningOverlayView {
private func _init() {
// overlay
blurVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
addSubview(blurVisualEffectView)
hintLabel.translatesAutoresizingMaskIntoConstraints = false
addSubview(hintLabel)
NSLayoutConstraint.activate([
blurVisualEffectView.topAnchor.constraint(equalTo: topAnchor),
blurVisualEffectView.leadingAnchor.constraint(equalTo: leadingAnchor),
blurVisualEffectView.trailingAnchor.constraint(equalTo: trailingAnchor),
blurVisualEffectView.bottomAnchor.constraint(equalTo: bottomAnchor),
hintLabel.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
trailingAnchor.constraint(equalTo: hintLabel.trailingAnchor, constant: 8),
centerYAnchor.constraint(equalTo: hintLabel.centerYAnchor, constant: 10),
])
vibrancyVisualEffectView.translatesAutoresizingMaskIntoConstraints = false
blurVisualEffectView.contentView.addSubview(vibrancyVisualEffectView)
NSLayoutConstraint.activate([
vibrancyVisualEffectView.topAnchor.constraint(equalTo: blurVisualEffectView.contentView.topAnchor),
vibrancyVisualEffectView.leadingAnchor.constraint(equalTo: blurVisualEffectView.contentView.leadingAnchor),
vibrancyVisualEffectView.trailingAnchor.constraint(equalTo: blurVisualEffectView.contentView.trailingAnchor),
vibrancyVisualEffectView.bottomAnchor.constraint(equalTo: blurVisualEffectView.contentView.bottomAnchor),
])
// alertImageView.translatesAutoresizingMaskIntoConstraints = false
// vibrancyVisualEffectView.contentView.addSubview(alertImageView)
// NSLayoutConstraint.activate([
// alertImageView.centerXAnchor.constraint(equalTo: vibrancyVisualEffectView.contentView.centerXAnchor),
// alertImageView.centerYAnchor.constraint(equalTo: vibrancyVisualEffectView.contentView.centerYAnchor),
// ])
tapGestureRecognizer.addTarget(self, action: #selector(ContentWarningOverlayView.tapGestureRecognizerHandler(_:)))
addGestureRecognizer(tapGestureRecognizer)
}
}
extension ContentWarningOverlayView {
@objc private func tapGestureRecognizerHandler(_ sender: UITapGestureRecognizer) {
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public)")
delegate?.contentWarningOverlayViewDidPressed(self)
}
}