feat: implement content warning dismiss action logic
This commit is contained in:
parent
f455faa273
commit
4d2e75f3ca
|
@ -49,7 +49,7 @@
|
||||||
2D76316B25C14D4C00929FB9 /* PublicTimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76316A25C14D4C00929FB9 /* PublicTimelineViewModel.swift */; };
|
2D76316B25C14D4C00929FB9 /* PublicTimelineViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76316A25C14D4C00929FB9 /* PublicTimelineViewModel.swift */; };
|
||||||
2D76317D25C14DF500929FB9 /* PublicTimelineViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76317C25C14DF400929FB9 /* PublicTimelineViewController+StatusProvider.swift */; };
|
2D76317D25C14DF500929FB9 /* PublicTimelineViewController+StatusProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76317C25C14DF400929FB9 /* PublicTimelineViewController+StatusProvider.swift */; };
|
||||||
2D76318325C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76318225C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift */; };
|
2D76318325C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76318225C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift */; };
|
||||||
2D76319F25C1521200929FB9 /* TimelineSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* TimelineSection.swift */; };
|
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* StatusSection.swift */; };
|
||||||
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */; };
|
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */; };
|
||||||
2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; };
|
2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; };
|
||||||
2D927F0225C7E4F2004F19B8 /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0125C7E4F2004F19B8 /* Mention.swift */; };
|
2D927F0225C7E4F2004F19B8 /* Mention.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D927F0125C7E4F2004F19B8 /* Mention.swift */; };
|
||||||
|
@ -239,7 +239,7 @@
|
||||||
2D76316A25C14D4C00929FB9 /* PublicTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineViewModel.swift; sourceTree = "<group>"; };
|
2D76316A25C14D4C00929FB9 /* PublicTimelineViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PublicTimelineViewModel.swift; sourceTree = "<group>"; };
|
||||||
2D76317C25C14DF400929FB9 /* PublicTimelineViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewController+StatusProvider.swift"; sourceTree = "<group>"; };
|
2D76317C25C14DF400929FB9 /* PublicTimelineViewController+StatusProvider.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewController+StatusProvider.swift"; sourceTree = "<group>"; };
|
||||||
2D76318225C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
2D76318225C14E8F00929FB9 /* PublicTimelineViewModel+Diffable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PublicTimelineViewModel+Diffable.swift"; sourceTree = "<group>"; };
|
||||||
2D76319E25C1521200929FB9 /* TimelineSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSection.swift; sourceTree = "<group>"; };
|
2D76319E25C1521200929FB9 /* StatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusSection.swift; sourceTree = "<group>"; };
|
||||||
2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = "<group>"; };
|
2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
|
2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
|
||||||
2D927F0125C7E4F2004F19B8 /* Mention.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = "<group>"; };
|
2D927F0125C7E4F2004F19B8 /* Mention.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Mention.swift; sourceTree = "<group>"; };
|
||||||
|
@ -514,8 +514,8 @@
|
||||||
2D69CFF225CA9E2200C3A1B2 /* Protocol */ = {
|
2D69CFF225CA9E2200C3A1B2 /* Protocol */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
DB5086AA25CC0BBB00C2C187 /* AvatarConfigurableView.swift */,
|
|
||||||
2D38F1FC25CD47D900561493 /* StatusProvider */,
|
2D38F1FC25CD47D900561493 /* StatusProvider */,
|
||||||
|
DB5086AA25CC0BBB00C2C187 /* AvatarConfigurableView.swift */,
|
||||||
2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */,
|
2D69CFF325CA9E2200C3A1B2 /* LoadMoreConfigurableTableViewContainer.swift */,
|
||||||
2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */,
|
2D38F1C525CD37F400561493 /* ContentOffsetAdjustableTimelineViewControllerDelegate.swift */,
|
||||||
2D38F20725CD491300561493 /* DisposeBagCollectable.swift */,
|
2D38F20725CD491300561493 /* DisposeBagCollectable.swift */,
|
||||||
|
@ -549,7 +549,7 @@
|
||||||
2D76319D25C151F600929FB9 /* Section */ = {
|
2D76319D25C151F600929FB9 /* Section */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2D76319E25C1521200929FB9 /* TimelineSection.swift */,
|
2D76319E25C1521200929FB9 /* StatusSection.swift */,
|
||||||
);
|
);
|
||||||
path = Section;
|
path = Section;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1382,7 +1382,7 @@
|
||||||
DB98334725C8056600AD9700 /* AuthenticationViewModel.swift in Sources */,
|
DB98334725C8056600AD9700 /* AuthenticationViewModel.swift in Sources */,
|
||||||
2D38F20825CD491300561493 /* DisposeBagCollectable.swift in Sources */,
|
2D38F20825CD491300561493 /* DisposeBagCollectable.swift in Sources */,
|
||||||
DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */,
|
DB0140CF25C42AEE00F9F3CF /* OSLog.swift in Sources */,
|
||||||
2D76319F25C1521200929FB9 /* TimelineSection.swift in Sources */,
|
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */,
|
||||||
DB118A8C25E4BFB500FAB162 /* HighlightDimmableButton.swift in Sources */,
|
DB118A8C25E4BFB500FAB162 /* HighlightDimmableButton.swift in Sources */,
|
||||||
DB084B5725CBC56C00F898ED /* Toot.swift in Sources */,
|
DB084B5725CBC56C00F898ED /* Toot.swift in Sources */,
|
||||||
DB0140A825C40C1500F9F3CF /* MastodonPinBasedAuthenticationViewModelNavigationDelegateShim.swift in Sources */,
|
DB0140A825C40C1500F9F3CF /* MastodonPinBasedAuthenticationViewModelNavigationDelegateShim.swift in Sources */,
|
||||||
|
|
|
@ -12,10 +12,11 @@ import MastodonSDK
|
||||||
|
|
||||||
/// Note: update Equatable when change case
|
/// Note: update Equatable when change case
|
||||||
enum Item {
|
enum Item {
|
||||||
case homeTimelineIndex(objectID: NSManagedObjectID, attribute: Attribute)
|
// timeline
|
||||||
|
case homeTimelineIndex(objectID: NSManagedObjectID, attribute: StatusTimelineAttribute)
|
||||||
|
|
||||||
// normal list
|
// normal list
|
||||||
case toot(objectID: NSManagedObjectID)
|
case toot(objectID: NSManagedObjectID, attribute: StatusTimelineAttribute)
|
||||||
|
|
||||||
// loader
|
// loader
|
||||||
case homeMiddleLoader(upperTimelineIndexAnchorObjectID: NSManagedObjectID)
|
case homeMiddleLoader(upperTimelineIndexAnchorObjectID: NSManagedObjectID)
|
||||||
|
@ -23,16 +24,31 @@ enum Item {
|
||||||
case bottomLoader
|
case bottomLoader
|
||||||
}
|
}
|
||||||
|
|
||||||
extension Item {
|
protocol StatusContentWarningAttribute {
|
||||||
class Attribute: Hashable {
|
var isStatusTextSensitive: Bool { get set }
|
||||||
var separatorLineStyle: SeparatorLineStyle = .indent
|
}
|
||||||
|
|
||||||
static func == (lhs: Item.Attribute, rhs: Item.Attribute) -> Bool {
|
extension Item {
|
||||||
return lhs.separatorLineStyle == rhs.separatorLineStyle
|
class StatusTimelineAttribute: Hashable, StatusContentWarningAttribute {
|
||||||
|
var separatorLineStyle: SeparatorLineStyle = .indent
|
||||||
|
var isStatusTextSensitive: Bool = false
|
||||||
|
|
||||||
|
public init(
|
||||||
|
separatorLineStyle: Item.StatusTimelineAttribute.SeparatorLineStyle = .indent,
|
||||||
|
isStatusTextSensitive: Bool
|
||||||
|
) {
|
||||||
|
self.separatorLineStyle = separatorLineStyle
|
||||||
|
self.isStatusTextSensitive = isStatusTextSensitive
|
||||||
|
}
|
||||||
|
|
||||||
|
static func == (lhs: Item.StatusTimelineAttribute, rhs: Item.StatusTimelineAttribute) -> Bool {
|
||||||
|
return lhs.separatorLineStyle == rhs.separatorLineStyle &&
|
||||||
|
lhs.isStatusTextSensitive == rhs.isStatusTextSensitive
|
||||||
}
|
}
|
||||||
|
|
||||||
func hash(into hasher: inout Hasher) {
|
func hash(into hasher: inout Hasher) {
|
||||||
hasher.combine(separatorLineStyle)
|
hasher.combine(separatorLineStyle)
|
||||||
|
hasher.combine(isStatusTextSensitive)
|
||||||
}
|
}
|
||||||
|
|
||||||
enum SeparatorLineStyle {
|
enum SeparatorLineStyle {
|
||||||
|
@ -48,7 +64,7 @@ extension Item: Equatable {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case (.homeTimelineIndex(let objectIDLeft, _), .homeTimelineIndex(let objectIDRight, _)):
|
case (.homeTimelineIndex(let objectIDLeft, _), .homeTimelineIndex(let objectIDRight, _)):
|
||||||
return objectIDLeft == objectIDRight
|
return objectIDLeft == objectIDRight
|
||||||
case (.toot(let objectIDLeft), .toot(let objectIDRight)):
|
case (.toot(let objectIDLeft, _), .toot(let objectIDRight, _)):
|
||||||
return objectIDLeft == objectIDRight
|
return objectIDLeft == objectIDRight
|
||||||
case (.bottomLoader, .bottomLoader):
|
case (.bottomLoader, .bottomLoader):
|
||||||
return true
|
return true
|
||||||
|
@ -67,7 +83,7 @@ extension Item: Hashable {
|
||||||
switch self {
|
switch self {
|
||||||
case .homeTimelineIndex(let objectID, _):
|
case .homeTimelineIndex(let objectID, _):
|
||||||
hasher.combine(objectID)
|
hasher.combine(objectID)
|
||||||
case .toot(let objectID):
|
case .toot(let objectID, _):
|
||||||
hasher.combine(objectID)
|
hasher.combine(objectID)
|
||||||
case .publicMiddleLoader(let upper):
|
case .publicMiddleLoader(let upper):
|
||||||
hasher.combine(String(describing: Item.publicMiddleLoader.self))
|
hasher.combine(String(describing: Item.publicMiddleLoader.self))
|
||||||
|
|
|
@ -11,11 +11,11 @@ import CoreDataStack
|
||||||
import os.log
|
import os.log
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
enum TimelineSection: Equatable, Hashable {
|
enum StatusSection: Equatable, Hashable {
|
||||||
case main
|
case main
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimelineSection {
|
extension StatusSection {
|
||||||
static func tableViewDiffableDataSource(
|
static func tableViewDiffableDataSource(
|
||||||
for tableView: UITableView,
|
for tableView: UITableView,
|
||||||
dependency: NeedsDependency,
|
dependency: NeedsDependency,
|
||||||
|
@ -23,29 +23,29 @@ extension TimelineSection {
|
||||||
timestampUpdatePublisher: AnyPublisher<Date, Never>,
|
timestampUpdatePublisher: AnyPublisher<Date, Never>,
|
||||||
timelinePostTableViewCellDelegate: StatusTableViewCellDelegate,
|
timelinePostTableViewCellDelegate: StatusTableViewCellDelegate,
|
||||||
timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?
|
timelineMiddleLoaderTableViewCellDelegate: TimelineMiddleLoaderTableViewCellDelegate?
|
||||||
) -> UITableViewDiffableDataSource<TimelineSection, Item> {
|
) -> UITableViewDiffableDataSource<StatusSection, Item> {
|
||||||
UITableViewDiffableDataSource(tableView: tableView) { [weak timelinePostTableViewCellDelegate, weak timelineMiddleLoaderTableViewCellDelegate] tableView, indexPath, item -> UITableViewCell? in
|
UITableViewDiffableDataSource(tableView: tableView) { [weak timelinePostTableViewCellDelegate, weak timelineMiddleLoaderTableViewCellDelegate] tableView, indexPath, item -> UITableViewCell? in
|
||||||
guard let timelinePostTableViewCellDelegate = timelinePostTableViewCellDelegate else { return UITableViewCell() }
|
guard let timelinePostTableViewCellDelegate = timelinePostTableViewCellDelegate else { return UITableViewCell() }
|
||||||
|
|
||||||
switch item {
|
switch item {
|
||||||
case .homeTimelineIndex(objectID: let objectID, attribute: _):
|
case .homeTimelineIndex(objectID: let objectID, let attribute):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
|
||||||
|
|
||||||
// configure cell
|
// configure cell
|
||||||
managedObjectContext.performAndWait {
|
managedObjectContext.performAndWait {
|
||||||
let timelineIndex = managedObjectContext.object(with: objectID) as! HomeTimelineIndex
|
let timelineIndex = managedObjectContext.object(with: objectID) as! HomeTimelineIndex
|
||||||
TimelineSection.configure(cell: cell, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, timestampUpdatePublisher: timestampUpdatePublisher, toot: timelineIndex.toot, requestUserID: timelineIndex.userID)
|
StatusSection.configure(cell: cell, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, timestampUpdatePublisher: timestampUpdatePublisher, toot: timelineIndex.toot, requestUserID: timelineIndex.userID, statusContentWarningAttribute: attribute)
|
||||||
}
|
}
|
||||||
cell.delegate = timelinePostTableViewCellDelegate
|
cell.delegate = timelinePostTableViewCellDelegate
|
||||||
return cell
|
return cell
|
||||||
case .toot(let objectID):
|
case .toot(let objectID, let attribute):
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: StatusTableViewCell.self), for: indexPath) as! StatusTableViewCell
|
||||||
let activeMastodonAuthenticationBox = dependency.context.authenticationService.activeMastodonAuthenticationBox.value
|
let activeMastodonAuthenticationBox = dependency.context.authenticationService.activeMastodonAuthenticationBox.value
|
||||||
let requestUserID = activeMastodonAuthenticationBox?.userID ?? ""
|
let requestUserID = activeMastodonAuthenticationBox?.userID ?? ""
|
||||||
// configure cell
|
// configure cell
|
||||||
managedObjectContext.performAndWait {
|
managedObjectContext.performAndWait {
|
||||||
let toot = managedObjectContext.object(with: objectID) as! Toot
|
let toot = managedObjectContext.object(with: objectID) as! Toot
|
||||||
TimelineSection.configure(cell: cell, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, timestampUpdatePublisher: timestampUpdatePublisher, toot: toot, requestUserID: requestUserID)
|
StatusSection.configure(cell: cell, readableLayoutFrame: tableView.readableContentGuide.layoutFrame, timestampUpdatePublisher: timestampUpdatePublisher, toot: toot, requestUserID: requestUserID, statusContentWarningAttribute: attribute)
|
||||||
}
|
}
|
||||||
cell.delegate = timelinePostTableViewCellDelegate
|
cell.delegate = timelinePostTableViewCellDelegate
|
||||||
return cell
|
return cell
|
||||||
|
@ -72,7 +72,8 @@ extension TimelineSection {
|
||||||
readableLayoutFrame: CGRect?,
|
readableLayoutFrame: CGRect?,
|
||||||
timestampUpdatePublisher: AnyPublisher<Date, Never>,
|
timestampUpdatePublisher: AnyPublisher<Date, Never>,
|
||||||
toot: Toot,
|
toot: Toot,
|
||||||
requestUserID: String
|
requestUserID: String,
|
||||||
|
statusContentWarningAttribute: StatusContentWarningAttribute?
|
||||||
) {
|
) {
|
||||||
// set header
|
// set header
|
||||||
cell.statusView.headerContainerStackView.isHidden = toot.reblog == nil
|
cell.statusView.headerContainerStackView.isHidden = toot.reblog == nil
|
||||||
|
@ -94,7 +95,8 @@ extension TimelineSection {
|
||||||
cell.statusView.activeTextLabel.config(content: (toot.reblog ?? toot).content)
|
cell.statusView.activeTextLabel.config(content: (toot.reblog ?? toot).content)
|
||||||
|
|
||||||
// set content warning
|
// set content warning
|
||||||
cell.statusView.updateContentWarningDisplay(isHidden: !(toot.reblog ?? toot).sensitive)
|
let isStatusTextSensitive = statusContentWarningAttribute?.isStatusTextSensitive ?? (toot.reblog ?? toot).sensitive
|
||||||
|
cell.statusView.updateContentWarningDisplay(isHidden: !isStatusTextSensitive)
|
||||||
cell.statusView.contentWarningTitle.text = (toot.reblog ?? toot).spoilerText.flatMap { spoilerText in
|
cell.statusView.contentWarningTitle.text = (toot.reblog ?? toot).spoilerText.flatMap { spoilerText in
|
||||||
return L10n.Common.Controls.Status.contentWarning + ": \(spoilerText)"
|
return L10n.Common.Controls.Status.contentWarning + ": \(spoilerText)"
|
||||||
} ?? L10n.Common.Controls.Status.contentWarning
|
} ?? L10n.Common.Controls.Status.contentWarning
|
||||||
|
@ -146,14 +148,14 @@ extension TimelineSection {
|
||||||
// toolbar
|
// toolbar
|
||||||
let replyCountTitle: String = {
|
let replyCountTitle: String = {
|
||||||
let count = (toot.reblog ?? toot).repliesCount?.intValue ?? 0
|
let count = (toot.reblog ?? toot).repliesCount?.intValue ?? 0
|
||||||
return TimelineSection.formattedNumberTitleForActionButton(count)
|
return StatusSection.formattedNumberTitleForActionButton(count)
|
||||||
}()
|
}()
|
||||||
cell.statusView.actionToolbarContainer.replyButton.setTitle(replyCountTitle, for: .normal)
|
cell.statusView.actionToolbarContainer.replyButton.setTitle(replyCountTitle, for: .normal)
|
||||||
|
|
||||||
let isLike = (toot.reblog ?? toot).favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false
|
let isLike = (toot.reblog ?? toot).favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false
|
||||||
let favoriteCountTitle: String = {
|
let favoriteCountTitle: String = {
|
||||||
let count = (toot.reblog ?? toot).favouritesCount.intValue
|
let count = (toot.reblog ?? toot).favouritesCount.intValue
|
||||||
return TimelineSection.formattedNumberTitleForActionButton(count)
|
return StatusSection.formattedNumberTitleForActionButton(count)
|
||||||
}()
|
}()
|
||||||
cell.statusView.actionToolbarContainer.starButton.setTitle(favoriteCountTitle, for: .normal)
|
cell.statusView.actionToolbarContainer.starButton.setTitle(favoriteCountTitle, for: .normal)
|
||||||
cell.statusView.actionToolbarContainer.isStarButtonHighlight = isLike
|
cell.statusView.actionToolbarContainer.isStarButtonHighlight = isLike
|
||||||
|
@ -179,7 +181,7 @@ extension TimelineSection {
|
||||||
|
|
||||||
let isLike = targetToot.favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false
|
let isLike = targetToot.favouritedBy.flatMap { $0.contains(where: { $0.id == requestUserID }) } ?? false
|
||||||
let favoriteCount = targetToot.favouritesCount.intValue
|
let favoriteCount = targetToot.favouritesCount.intValue
|
||||||
let favoriteCountTitle = TimelineSection.formattedNumberTitleForActionButton(favoriteCount)
|
let favoriteCountTitle = StatusSection.formattedNumberTitleForActionButton(favoriteCount)
|
||||||
cell.statusView.actionToolbarContainer.starButton.setTitle(favoriteCountTitle, for: .normal)
|
cell.statusView.actionToolbarContainer.starButton.setTitle(favoriteCountTitle, for: .normal)
|
||||||
cell.statusView.actionToolbarContainer.isStarButtonHighlight = isLike
|
cell.statusView.actionToolbarContainer.isStarButtonHighlight = isLike
|
||||||
os_log("%{public}s[%{public}ld], %{public}s: like count label for toot %s did update: %ld", (#file as NSString).lastPathComponent, #line, #function, targetToot.id, favoriteCount)
|
os_log("%{public}s[%{public}ld], %{public}s: like count label for toot %s did update: %ld", (#file as NSString).lastPathComponent, #line, #function, targetToot.id, favoriteCount)
|
||||||
|
@ -188,7 +190,7 @@ extension TimelineSection {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension TimelineSection {
|
extension StatusSection {
|
||||||
private static func formattedNumberTitleForActionButton(_ number: Int?) -> String {
|
private static func formattedNumberTitleForActionButton(_ number: Int?) -> String {
|
||||||
guard let number = number, number > 0 else { return "" }
|
guard let number = number, number > 0 else { return "" }
|
||||||
return String(number)
|
return String(number)
|
|
@ -20,5 +20,26 @@ extension StatusTableViewCellDelegate where Self: StatusProvider {
|
||||||
StatusProviderFacade.responseToStatusLikeAction(provider: self, cell: cell)
|
StatusProviderFacade.responseToStatusLikeAction(provider: self, cell: cell)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, contentWarningActionButtonPressed button: UIButton) {
|
||||||
|
guard let diffableDataSource = self.tableViewDiffableDataSource else { return }
|
||||||
|
item(for: cell, indexPath: nil)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] item in
|
||||||
|
guard let _ = self else { return }
|
||||||
|
guard let item = item else { return }
|
||||||
|
switch item {
|
||||||
|
case .homeTimelineIndex(_, let attribute):
|
||||||
|
attribute.isStatusTextSensitive = false
|
||||||
|
case .toot(_, let attribute):
|
||||||
|
attribute.isStatusTextSensitive = false
|
||||||
|
default:
|
||||||
|
return
|
||||||
|
}
|
||||||
|
var snapshot = diffableDataSource.snapshot()
|
||||||
|
snapshot.reloadItems([item])
|
||||||
|
diffableDataSource.apply(snapshot)
|
||||||
|
}
|
||||||
|
.store(in: &cell.disposeBag)
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -13,4 +13,7 @@ protocol StatusProvider: NeedsDependency & DisposeBagCollectable & UIViewControl
|
||||||
func toot() -> Future<Toot?, Never>
|
func toot() -> Future<Toot?, Never>
|
||||||
func toot(for cell: UITableViewCell, indexPath: IndexPath?) -> Future<Toot?, Never>
|
func toot(for cell: UITableViewCell, indexPath: IndexPath?) -> Future<Toot?, Never>
|
||||||
func toot(for cell: UICollectionViewCell) -> Future<Toot?, Never>
|
func toot(for cell: UICollectionViewCell) -> Future<Toot?, Never>
|
||||||
|
|
||||||
|
var tableViewDiffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>? { get }
|
||||||
|
func item(for cell: UITableViewCell, indexPath: IndexPath?) -> Future<Item?, Never>
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,7 +12,7 @@ import CoreDataStack
|
||||||
|
|
||||||
// MARK: - StatusProvider
|
// MARK: - StatusProvider
|
||||||
extension HomeTimelineViewController: StatusProvider {
|
extension HomeTimelineViewController: StatusProvider {
|
||||||
|
|
||||||
func toot() -> Future<Toot?, Never> {
|
func toot() -> Future<Toot?, Never> {
|
||||||
return Future { promise in promise(.success(nil)) }
|
return Future { promise in promise(.success(nil)) }
|
||||||
}
|
}
|
||||||
|
@ -47,4 +47,25 @@ extension HomeTimelineViewController: StatusProvider {
|
||||||
return Future { promise in promise(.success(nil)) }
|
return Future { promise in promise(.success(nil)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tableViewDiffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>? {
|
||||||
|
return viewModel.diffableDataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func item(for cell: UITableViewCell, indexPath: IndexPath?) -> Future<Item?, Never> {
|
||||||
|
return Future { promise in
|
||||||
|
guard let diffableDataSource = self.viewModel.diffableDataSource else {
|
||||||
|
assertionFailure()
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let indexPath = indexPath ?? self.tableView.indexPath(for: cell),
|
||||||
|
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
promise(.success(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,7 +15,7 @@ import GameplayKit
|
||||||
import MastodonSDK
|
import MastodonSDK
|
||||||
import AlamofireImage
|
import AlamofireImage
|
||||||
|
|
||||||
final class HomeTimelineViewController: UIViewController, NeedsDependency,StatusTableViewCellDelegate {
|
final class HomeTimelineViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
weak var context: AppContext! { willSet { precondition(!isViewLoaded) } }
|
||||||
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
weak var coordinator: SceneCoordinator! { willSet { precondition(!isViewLoaded) } }
|
||||||
|
@ -313,3 +313,6 @@ extension HomeTimelineViewController: ScrollViewContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - StatusTableViewCellDelegate
|
||||||
|
extension HomeTimelineViewController: StatusTableViewCellDelegate { }
|
||||||
|
|
|
@ -23,7 +23,7 @@ extension HomeTimelineViewModel {
|
||||||
.share()
|
.share()
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
|
||||||
diffableDataSource = TimelineSection.tableViewDiffableDataSource(
|
diffableDataSource = StatusSection.tableViewDiffableDataSource(
|
||||||
for: tableView,
|
for: tableView,
|
||||||
dependency: dependency,
|
dependency: dependency,
|
||||||
managedObjectContext: fetchedResultsController.managedObjectContext,
|
managedObjectContext: fetchedResultsController.managedObjectContext,
|
||||||
|
@ -73,7 +73,7 @@ extension HomeTimelineViewModel: NSFetchedResultsControllerDelegate {
|
||||||
|
|
||||||
// that's will be the most fastest fetch because of upstream just update and no modify needs consider
|
// that's will be the most fastest fetch because of upstream just update and no modify needs consider
|
||||||
|
|
||||||
var oldSnapshotAttributeDict: [NSManagedObjectID : Item.Attribute] = [:]
|
var oldSnapshotAttributeDict: [NSManagedObjectID : Item.StatusTimelineAttribute] = [:]
|
||||||
|
|
||||||
for item in oldSnapshot.itemIdentifiers {
|
for item in oldSnapshot.itemIdentifiers {
|
||||||
guard case let .homeTimelineIndex(objectID, attribute) = item else { continue }
|
guard case let .homeTimelineIndex(objectID, attribute) = item else { continue }
|
||||||
|
@ -83,7 +83,7 @@ extension HomeTimelineViewModel: NSFetchedResultsControllerDelegate {
|
||||||
var newTimelineItems: [Item] = []
|
var newTimelineItems: [Item] = []
|
||||||
|
|
||||||
for (i, timelineIndex) in timelineIndexes.enumerated() {
|
for (i, timelineIndex) in timelineIndexes.enumerated() {
|
||||||
let attribute = oldSnapshotAttributeDict[timelineIndex.objectID] ?? Item.Attribute()
|
let attribute = oldSnapshotAttributeDict[timelineIndex.objectID] ?? Item.StatusTimelineAttribute(isStatusTextSensitive: timelineIndex.toot.sensitive)
|
||||||
|
|
||||||
// append new item into snapshot
|
// append new item into snapshot
|
||||||
newTimelineItems.append(.homeTimelineIndex(objectID: timelineIndex.objectID, attribute: attribute))
|
newTimelineItems.append(.homeTimelineIndex(objectID: timelineIndex.objectID, attribute: attribute))
|
||||||
|
@ -103,7 +103,7 @@ extension HomeTimelineViewModel: NSFetchedResultsControllerDelegate {
|
||||||
}
|
}
|
||||||
} // end for
|
} // end for
|
||||||
|
|
||||||
var newSnapshot = NSDiffableDataSourceSnapshot<TimelineSection, Item>()
|
var newSnapshot = NSDiffableDataSourceSnapshot<StatusSection, Item>()
|
||||||
newSnapshot.appendSections([.main])
|
newSnapshot.appendSections([.main])
|
||||||
newSnapshot.appendItems(newTimelineItems, toSection: .main)
|
newSnapshot.appendItems(newTimelineItems, toSection: .main)
|
||||||
|
|
||||||
|
@ -142,8 +142,8 @@ extension HomeTimelineViewModel: NSFetchedResultsControllerDelegate {
|
||||||
private func calculateReloadSnapshotDifference<T: Hashable>(
|
private func calculateReloadSnapshotDifference<T: Hashable>(
|
||||||
navigationBar: UINavigationBar,
|
navigationBar: UINavigationBar,
|
||||||
tableView: UITableView,
|
tableView: UITableView,
|
||||||
oldSnapshot: NSDiffableDataSourceSnapshot<TimelineSection, T>,
|
oldSnapshot: NSDiffableDataSourceSnapshot<StatusSection, T>,
|
||||||
newSnapshot: NSDiffableDataSourceSnapshot<TimelineSection, T>
|
newSnapshot: NSDiffableDataSourceSnapshot<StatusSection, T>
|
||||||
) -> Difference<T>? {
|
) -> Difference<T>? {
|
||||||
guard oldSnapshot.numberOfItems != 0 else { return nil }
|
guard oldSnapshot.numberOfItems != 0 else { return nil }
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ final class HomeTimelineViewModel: NSObject {
|
||||||
lazy var loadOldestStateMachinePublisher = CurrentValueSubject<LoadOldestState?, Never>(nil)
|
lazy var loadOldestStateMachinePublisher = CurrentValueSubject<LoadOldestState?, Never>(nil)
|
||||||
// middle loader
|
// middle loader
|
||||||
let loadMiddleSateMachineList = CurrentValueSubject<[NSManagedObjectID: GKStateMachine], Never>([:]) // TimelineIndex.objectID : middle loading state machine
|
let loadMiddleSateMachineList = CurrentValueSubject<[NSManagedObjectID: GKStateMachine], Never>([:]) // TimelineIndex.objectID : middle loading state machine
|
||||||
var diffableDataSource: UITableViewDiffableDataSource<TimelineSection, Item>?
|
var diffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>?
|
||||||
var cellFrameCache = NSCache<NSNumber, NSValue>()
|
var cellFrameCache = NSCache<NSNumber, NSValue>()
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ extension PublicTimelineViewController: StatusProvider {
|
||||||
}
|
}
|
||||||
|
|
||||||
switch item {
|
switch item {
|
||||||
case .toot(let objectID):
|
case .toot(let objectID, _):
|
||||||
let managedObjectContext = self.viewModel.fetchedResultsController.managedObjectContext
|
let managedObjectContext = self.viewModel.fetchedResultsController.managedObjectContext
|
||||||
managedObjectContext.perform {
|
managedObjectContext.perform {
|
||||||
let toot = managedObjectContext.object(with: objectID) as? Toot
|
let toot = managedObjectContext.object(with: objectID) as? Toot
|
||||||
|
@ -48,4 +48,25 @@ extension PublicTimelineViewController: StatusProvider {
|
||||||
return Future { promise in promise(.success(nil)) }
|
return Future { promise in promise(.success(nil)) }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var tableViewDiffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>? {
|
||||||
|
return viewModel.diffableDataSource
|
||||||
|
}
|
||||||
|
|
||||||
|
func item(for cell: UITableViewCell, indexPath: IndexPath?) -> Future<Item?, Never> {
|
||||||
|
return Future { promise in
|
||||||
|
guard let diffableDataSource = self.viewModel.diffableDataSource else {
|
||||||
|
assertionFailure()
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
guard let indexPath = indexPath ?? self.tableView.indexPath(for: cell),
|
||||||
|
let item = diffableDataSource.itemIdentifier(for: indexPath) else {
|
||||||
|
promise(.success(nil))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
promise(.success(item))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ extension PublicTimelineViewModel {
|
||||||
.share()
|
.share()
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
|
||||||
diffableDataSource = TimelineSection.tableViewDiffableDataSource(
|
diffableDataSource = StatusSection.tableViewDiffableDataSource(
|
||||||
for: tableView,
|
for: tableView,
|
||||||
dependency: dependency,
|
dependency: dependency,
|
||||||
managedObjectContext: fetchedResultsController.managedObjectContext,
|
managedObjectContext: fetchedResultsController.managedObjectContext,
|
||||||
|
@ -50,11 +50,18 @@ extension PublicTimelineViewModel: NSFetchedResultsControllerDelegate {
|
||||||
return indexes.firstIndex(of: toot.id).map { index in (index, toot) }
|
return indexes.firstIndex(of: toot.id).map { index in (index, toot) }
|
||||||
}
|
}
|
||||||
.sorted { $0.0 < $1.0 }
|
.sorted { $0.0 < $1.0 }
|
||||||
|
var oldSnapshotAttributeDict: [NSManagedObjectID: Item.StatusTimelineAttribute] = [:]
|
||||||
|
for item in self.items.value {
|
||||||
|
guard case let .toot(objectID, attribute) = item else { continue }
|
||||||
|
oldSnapshotAttributeDict[objectID] = attribute
|
||||||
|
}
|
||||||
|
|
||||||
var items = [Item]()
|
var items = [Item]()
|
||||||
for tuple in indexTootTuples {
|
for (_, toot) in indexTootTuples {
|
||||||
items.append(Item.toot(objectID: tuple.1.objectID))
|
let attribute = oldSnapshotAttributeDict[toot.objectID] ?? Item.StatusTimelineAttribute(isStatusTextSensitive: toot.sensitive)
|
||||||
if tootIDsWhichHasGap.contains(tuple.1.id) {
|
items.append(Item.toot(objectID: toot.objectID, attribute: attribute))
|
||||||
items.append(Item.publicMiddleLoader(tootID: tuple.1.id))
|
if tootIDsWhichHasGap.contains(toot.id) {
|
||||||
|
items.append(Item.publicMiddleLoader(tootID: toot.id))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ class PublicTimelineViewModel: NSObject {
|
||||||
//
|
//
|
||||||
var tootIDsWhichHasGap = [String]()
|
var tootIDsWhichHasGap = [String]()
|
||||||
// output
|
// output
|
||||||
var diffableDataSource: UITableViewDiffableDataSource<TimelineSection, Item>?
|
var diffableDataSource: UITableViewDiffableDataSource<StatusSection, Item>?
|
||||||
|
|
||||||
lazy var stateMachine: GKStateMachine = {
|
lazy var stateMachine: GKStateMachine = {
|
||||||
let stateMachine = GKStateMachine(states: [
|
let stateMachine = GKStateMachine(states: [
|
||||||
|
@ -82,7 +82,7 @@ class PublicTimelineViewModel: NSObject {
|
||||||
let oldSnapshot = diffableDataSource.snapshot()
|
let oldSnapshot = diffableDataSource.snapshot()
|
||||||
os_log("%{public}s[%{public}ld], %{public}s: items did change", (#file as NSString).lastPathComponent, #line, #function)
|
os_log("%{public}s[%{public}ld], %{public}s: items did change", (#file as NSString).lastPathComponent, #line, #function)
|
||||||
|
|
||||||
var snapshot = NSDiffableDataSourceSnapshot<TimelineSection, Item>()
|
var snapshot = NSDiffableDataSourceSnapshot<StatusSection, Item>()
|
||||||
snapshot.appendSections([.main])
|
snapshot.appendSections([.main])
|
||||||
snapshot.appendItems(items)
|
snapshot.appendItems(items)
|
||||||
if let currentState = self.stateMachine.currentState {
|
if let currentState = self.stateMachine.currentState {
|
||||||
|
@ -140,8 +140,8 @@ class PublicTimelineViewModel: NSObject {
|
||||||
private func calculateReloadSnapshotDifference<T: Hashable>(
|
private func calculateReloadSnapshotDifference<T: Hashable>(
|
||||||
navigationBar: UINavigationBar,
|
navigationBar: UINavigationBar,
|
||||||
tableView: UITableView,
|
tableView: UITableView,
|
||||||
oldSnapshot: NSDiffableDataSourceSnapshot<TimelineSection, T>,
|
oldSnapshot: NSDiffableDataSourceSnapshot<StatusSection, T>,
|
||||||
newSnapshot: NSDiffableDataSourceSnapshot<TimelineSection, T>
|
newSnapshot: NSDiffableDataSourceSnapshot<StatusSection, T>
|
||||||
) -> Difference<T>? {
|
) -> Difference<T>? {
|
||||||
guard oldSnapshot.numberOfItems != 0 else { return nil }
|
guard oldSnapshot.numberOfItems != 0 else { return nil }
|
||||||
|
|
||||||
|
|
|
@ -5,17 +5,24 @@
|
||||||
// Created by sxiaojian on 2021/1/28.
|
// Created by sxiaojian on 2021/1/28.
|
||||||
//
|
//
|
||||||
|
|
||||||
|
import os.log
|
||||||
import UIKit
|
import UIKit
|
||||||
import AVKit
|
import AVKit
|
||||||
import ActiveLabel
|
import ActiveLabel
|
||||||
import AlamofireImage
|
import AlamofireImage
|
||||||
|
|
||||||
|
protocol StatusViewDelegate: class {
|
||||||
|
func statusView(_ statusView: StatusView, contentWarningActionButtonPressed button: UIButton)
|
||||||
|
}
|
||||||
|
|
||||||
final class StatusView: UIView {
|
final class StatusView: UIView {
|
||||||
|
|
||||||
static let avatarImageSize = CGSize(width: 42, height: 42)
|
static let avatarImageSize = CGSize(width: 42, height: 42)
|
||||||
static let avatarImageCornerRadius: CGFloat = 4
|
static let avatarImageCornerRadius: CGFloat = 4
|
||||||
static let contentWarningBlurRadius: CGFloat = 12
|
static let contentWarningBlurRadius: CGFloat = 12
|
||||||
|
|
||||||
|
weak var delegate: StatusViewDelegate?
|
||||||
|
|
||||||
let headerContainerStackView = UIStackView()
|
let headerContainerStackView = UIStackView()
|
||||||
|
|
||||||
let headerIconLabel: UILabel = {
|
let headerIconLabel: UILabel = {
|
||||||
|
@ -231,7 +238,7 @@ extension StatusView {
|
||||||
statusContentWarningContainerStackView.distribution = .fill
|
statusContentWarningContainerStackView.distribution = .fill
|
||||||
statusContentWarningContainerStackView.alignment = .center
|
statusContentWarningContainerStackView.alignment = .center
|
||||||
statusTextContainerView.addSubview(statusContentWarningContainerStackView)
|
statusTextContainerView.addSubview(statusContentWarningContainerStackView)
|
||||||
statusContentWarningContainerStackViewBottomLayoutConstraint = statusTextContainerView.bottomAnchor.constraint(greaterThanOrEqualTo: statusContentWarningContainerStackView.bottomAnchor, constant: 8)
|
statusContentWarningContainerStackViewBottomLayoutConstraint = statusTextContainerView.bottomAnchor.constraint(greaterThanOrEqualTo: statusContentWarningContainerStackView.bottomAnchor)
|
||||||
NSLayoutConstraint.activate([
|
NSLayoutConstraint.activate([
|
||||||
statusContentWarningContainerStackView.topAnchor.constraint(equalTo: statusTextContainerView.topAnchor),
|
statusContentWarningContainerStackView.topAnchor.constraint(equalTo: statusTextContainerView.topAnchor),
|
||||||
statusContentWarningContainerStackView.leadingAnchor.constraint(equalTo: statusTextContainerView.leadingAnchor),
|
statusContentWarningContainerStackView.leadingAnchor.constraint(equalTo: statusTextContainerView.leadingAnchor),
|
||||||
|
@ -252,6 +259,8 @@ extension StatusView {
|
||||||
contentWarningBlurContentImageView.isHidden = true
|
contentWarningBlurContentImageView.isHidden = true
|
||||||
statusContentWarningContainerStackView.isHidden = true
|
statusContentWarningContainerStackView.isHidden = true
|
||||||
statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false
|
statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false
|
||||||
|
|
||||||
|
contentWarningActionButton.addTarget(self, action: #selector(StatusView.contentWarningActionButtonPressed(_:)), for: .touchUpInside)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -284,6 +293,13 @@ extension StatusView {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension StatusView {
|
||||||
|
@objc private func contentWarningActionButtonPressed(_ sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
delegate?.statusView(self, contentWarningActionButtonPressed: sender)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension StatusView: AvatarConfigurableView {
|
extension StatusView: AvatarConfigurableView {
|
||||||
static var configurableAvatarImageSize: CGSize { return Self.avatarImageSize }
|
static var configurableAvatarImageSize: CGSize { return Self.avatarImageSize }
|
||||||
static var configurableAvatarImageCornerRadius: CGFloat { return 4 }
|
static var configurableAvatarImageCornerRadius: CGFloat { return 4 }
|
||||||
|
|
|
@ -13,6 +13,7 @@ import Combine
|
||||||
|
|
||||||
protocol StatusTableViewCellDelegate: class {
|
protocol StatusTableViewCellDelegate: class {
|
||||||
func statusTableViewCell(_ cell: StatusTableViewCell, actionToolbarContainer: ActionToolbarContainer, likeButtonDidPressed sender: UIButton)
|
func statusTableViewCell(_ cell: StatusTableViewCell, actionToolbarContainer: ActionToolbarContainer, likeButtonDidPressed sender: UIButton)
|
||||||
|
func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, contentWarningActionButtonPressed button: UIButton)
|
||||||
}
|
}
|
||||||
|
|
||||||
final class StatusTableViewCell: UITableViewCell {
|
final class StatusTableViewCell: UITableViewCell {
|
||||||
|
@ -69,11 +70,20 @@ extension StatusTableViewCell {
|
||||||
bottomPaddingView.heightAnchor.constraint(equalToConstant: 10).priority(.defaultHigh),
|
bottomPaddingView.heightAnchor.constraint(equalToConstant: 10).priority(.defaultHigh),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
statusView.delegate = self
|
||||||
statusView.actionToolbarContainer.delegate = self
|
statusView.actionToolbarContainer.delegate = self
|
||||||
bottomPaddingView.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color
|
bottomPaddingView.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - StatusViewDelegate
|
||||||
|
extension StatusTableViewCell: StatusViewDelegate {
|
||||||
|
func statusView(_ statusView: StatusView, contentWarningActionButtonPressed button: UIButton) {
|
||||||
|
delegate?.statusTableViewCell(self, statusView: statusView, contentWarningActionButtonPressed: button)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - ActionToolbarContainerDelegate
|
// MARK: - ActionToolbarContainerDelegate
|
||||||
extension StatusTableViewCell: ActionToolbarContainerDelegate {
|
extension StatusTableViewCell: ActionToolbarContainerDelegate {
|
||||||
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, replayButtonDidPressed sender: UIButton) {
|
func actionToolbarContainer(_ actionToolbarContainer: ActionToolbarContainer, replayButtonDidPressed sender: UIButton) {
|
||||||
|
|
Loading…
Reference in New Issue