feat: make toot poll display
This commit is contained in:
parent
8b63c2fda1
commit
aea2ddc078
|
@ -150,7 +150,7 @@
|
||||||
<relationship name="favouritedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="favourite" inverseEntity="MastodonUser"/>
|
<relationship name="favouritedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="favourite" inverseEntity="MastodonUser"/>
|
||||||
<relationship name="homeTimelineIndexes" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="HomeTimelineIndex" inverseName="toot" inverseEntity="HomeTimelineIndex"/>
|
<relationship name="homeTimelineIndexes" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="HomeTimelineIndex" inverseName="toot" inverseEntity="HomeTimelineIndex"/>
|
||||||
<relationship name="mediaAttachments" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Attachment" inverseName="toot" inverseEntity="Attachment"/>
|
<relationship name="mediaAttachments" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Attachment" inverseName="toot" inverseEntity="Attachment"/>
|
||||||
<relationship name="mentions" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mention" inverseName="toot" inverseEntity="Mention"/>
|
<relationship name="mentions" optional="YES" toMany="YES" deletionRule="Cascade" destinationEntity="Mention" inverseName="toot" inverseEntity="Mention"/>
|
||||||
<relationship name="mutedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muted" inverseEntity="MastodonUser"/>
|
<relationship name="mutedBy" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="muted" inverseEntity="MastodonUser"/>
|
||||||
<relationship name="pinnedBy" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="pinnedToot" inverseEntity="MastodonUser"/>
|
<relationship name="pinnedBy" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser" inverseName="pinnedToot" inverseEntity="MastodonUser"/>
|
||||||
<relationship name="poll" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Poll" inverseName="toot" inverseEntity="Poll"/>
|
<relationship name="poll" optional="YES" maxCount="1" deletionRule="Cascade" destinationEntity="Poll" inverseName="toot" inverseEntity="Poll"/>
|
||||||
|
@ -168,9 +168,9 @@
|
||||||
<element name="MastodonAuthentication" positionX="18" positionY="162" width="128" height="209"/>
|
<element name="MastodonAuthentication" positionX="18" positionY="162" width="128" height="209"/>
|
||||||
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="299"/>
|
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="299"/>
|
||||||
<element name="Mention" positionX="9" positionY="108" width="128" height="134"/>
|
<element name="Mention" positionX="9" positionY="108" width="128" height="134"/>
|
||||||
<element name="Tag" positionX="18" positionY="117" width="128" height="119"/>
|
|
||||||
<element name="Toot" positionX="0" positionY="0" width="128" height="539"/>
|
|
||||||
<element name="Poll" positionX="72" positionY="162" width="128" height="179"/>
|
<element name="Poll" positionX="72" positionY="162" width="128" height="179"/>
|
||||||
<element name="PollOption" positionX="81" positionY="171" width="128" height="134"/>
|
<element name="PollOption" positionX="81" positionY="171" width="128" height="134"/>
|
||||||
|
<element name="Tag" positionX="18" positionY="117" width="128" height="119"/>
|
||||||
|
<element name="Toot" positionX="0" positionY="0" width="128" height="539"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
|
@ -153,7 +153,7 @@
|
||||||
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */; };
|
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */; };
|
||||||
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55C25C138B7002E6C99 /* UIViewController.swift */; };
|
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF55C25C138B7002E6C99 /* UIViewController.swift */; };
|
||||||
DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */; };
|
DB8AF56825C13E2A002E6C99 /* HomeTimelineIndex.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */; };
|
||||||
DB92CF7225E7BB98002C1017 /* PollTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB92CF7125E7BB98002C1017 /* PollTableViewCell.swift */; };
|
DB92CF7225E7BB98002C1017 /* PollOptionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */; };
|
||||||
DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98336A25C9420100AD9700 /* APIService+App.swift */; };
|
DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98336A25C9420100AD9700 /* APIService+App.swift */; };
|
||||||
DB98337125C9443200AD9700 /* APIService+Authentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98337025C9443200AD9700 /* APIService+Authentication.swift */; };
|
DB98337125C9443200AD9700 /* APIService+Authentication.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98337025C9443200AD9700 /* APIService+Authentication.swift */; };
|
||||||
DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98337E25C9452D00AD9700 /* APIService+APIError.swift */; };
|
DB98337F25C9452D00AD9700 /* APIService+APIError.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB98337E25C9452D00AD9700 /* APIService+APIError.swift */; };
|
||||||
|
@ -379,7 +379,7 @@
|
||||||
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = "<group>"; };
|
DB8AF54F25C13703002E6C99 /* MainTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MainTabBarController.swift; sourceTree = "<group>"; };
|
||||||
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
DB8AF55C25C138B7002E6C99 /* UIViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UIViewController.swift; sourceTree = "<group>"; };
|
||||||
DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineIndex.swift; sourceTree = "<group>"; };
|
DB8AF56725C13E2A002E6C99 /* HomeTimelineIndex.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineIndex.swift; sourceTree = "<group>"; };
|
||||||
DB92CF7125E7BB98002C1017 /* PollTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollTableViewCell.swift; sourceTree = "<group>"; };
|
DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionTableViewCell.swift; sourceTree = "<group>"; };
|
||||||
DB98336A25C9420100AD9700 /* APIService+App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+App.swift"; sourceTree = "<group>"; };
|
DB98336A25C9420100AD9700 /* APIService+App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+App.swift"; sourceTree = "<group>"; };
|
||||||
DB98337025C9443200AD9700 /* APIService+Authentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Authentication.swift"; sourceTree = "<group>"; };
|
DB98337025C9443200AD9700 /* APIService+Authentication.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Authentication.swift"; sourceTree = "<group>"; };
|
||||||
DB98337E25C9452D00AD9700 /* APIService+APIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+APIError.swift"; sourceTree = "<group>"; };
|
DB98337E25C9452D00AD9700 /* APIService+APIError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+APIError.swift"; sourceTree = "<group>"; };
|
||||||
|
@ -684,7 +684,7 @@
|
||||||
2DA7D04325CA52B200804E11 /* TimelineLoaderTableViewCell.swift */,
|
2DA7D04325CA52B200804E11 /* TimelineLoaderTableViewCell.swift */,
|
||||||
2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */,
|
2DA7D04925CA52CB00804E11 /* TimelineBottomLoaderTableViewCell.swift */,
|
||||||
2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */,
|
2D32EAAB25CB96DC00C9ED86 /* TimelineMiddleLoaderTableViewCell.swift */,
|
||||||
DB92CF7125E7BB98002C1017 /* PollTableViewCell.swift */,
|
DB92CF7125E7BB98002C1017 /* PollOptionTableViewCell.swift */,
|
||||||
);
|
);
|
||||||
path = TableviewCell;
|
path = TableviewCell;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1469,7 +1469,7 @@
|
||||||
2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */,
|
2D5A3D3825CF8D9F002347D6 /* ScrollViewContainer.swift in Sources */,
|
||||||
0FAA101225E105390017CCDE /* PrimaryActionButton.swift in Sources */,
|
0FAA101225E105390017CCDE /* PrimaryActionButton.swift in Sources */,
|
||||||
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
|
DB8AF53025C13561002E6C99 /* AppContext.swift in Sources */,
|
||||||
DB92CF7225E7BB98002C1017 /* PollTableViewCell.swift in Sources */,
|
DB92CF7225E7BB98002C1017 /* PollOptionTableViewCell.swift in Sources */,
|
||||||
DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */,
|
DB72602725E36A6F00235243 /* MastodonServerRulesViewModel.swift in Sources */,
|
||||||
2D364F7225E66D7500204FDC /* MastodonResendEmailViewController.swift in Sources */,
|
2D364F7225E66D7500204FDC /* MastodonResendEmailViewController.swift in Sources */,
|
||||||
2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
|
2D38F1F125CD477D00561493 /* HomeTimelineViewModel+LoadMiddleState.swift in Sources */,
|
||||||
|
|
|
@ -9,7 +9,7 @@ import Foundation
|
||||||
import CoreData
|
import CoreData
|
||||||
|
|
||||||
enum PollItem {
|
enum PollItem {
|
||||||
case pollOpion(objectID: NSManagedObjectID, attribute: Attribute)
|
case opion(objectID: NSManagedObjectID, attribute: Attribute)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -17,6 +17,10 @@ extension PollItem {
|
||||||
class Attribute: Hashable {
|
class Attribute: Hashable {
|
||||||
var voted: Bool = false
|
var voted: Bool = false
|
||||||
|
|
||||||
|
init(voted: Bool = false) {
|
||||||
|
self.voted = voted
|
||||||
|
}
|
||||||
|
|
||||||
static func == (lhs: PollItem.Attribute, rhs: PollItem.Attribute) -> Bool {
|
static func == (lhs: PollItem.Attribute, rhs: PollItem.Attribute) -> Bool {
|
||||||
return lhs.voted == rhs.voted
|
return lhs.voted == rhs.voted
|
||||||
}
|
}
|
||||||
|
@ -30,10 +34,8 @@ extension PollItem {
|
||||||
extension PollItem: Equatable {
|
extension PollItem: Equatable {
|
||||||
static func == (lhs: PollItem, rhs: PollItem) -> Bool {
|
static func == (lhs: PollItem, rhs: PollItem) -> Bool {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case (.pollOpion(let objectIDLeft, _), .pollOpion(let objectIDRight, _)):
|
case (.opion(let objectIDLeft, _), .opion(let objectIDRight, _)):
|
||||||
return objectIDLeft == objectIDRight
|
return objectIDLeft == objectIDRight
|
||||||
default:
|
|
||||||
return false
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -42,7 +44,7 @@ extension PollItem: Equatable {
|
||||||
extension PollItem: Hashable {
|
extension PollItem: Hashable {
|
||||||
func hash(into hasher: inout Hasher) {
|
func hash(into hasher: inout Hasher) {
|
||||||
switch self {
|
switch self {
|
||||||
case .pollOpion(let objectID, _):
|
case .opion(let objectID, _):
|
||||||
hasher.combine(objectID)
|
hasher.combine(objectID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import UIKit
|
||||||
import CoreData
|
import CoreData
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
|
|
||||||
enum PollSection {
|
enum PollSection: Equatable, Hashable {
|
||||||
case main
|
case main
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,7 +19,25 @@ extension PollSection {
|
||||||
managedObjectContext: NSManagedObjectContext
|
managedObjectContext: NSManagedObjectContext
|
||||||
) -> UITableViewDiffableDataSource<PollSection, PollItem> {
|
) -> UITableViewDiffableDataSource<PollSection, PollItem> {
|
||||||
return UITableViewDiffableDataSource<PollSection, PollItem>(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
return UITableViewDiffableDataSource<PollSection, PollItem>(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
||||||
return nil
|
switch item {
|
||||||
|
case .opion(let objectID, let attribute):
|
||||||
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: PollOptionTableViewCell.self), for: indexPath) as! PollOptionTableViewCell
|
||||||
|
managedObjectContext.performAndWait {
|
||||||
|
let option = managedObjectContext.object(with: objectID) as! PollOption
|
||||||
|
PollSection.configure(cell: cell, pollOption: option, itemAttribute: attribute)
|
||||||
|
}
|
||||||
|
return cell
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension PollSection {
|
||||||
|
static func configure(
|
||||||
|
cell: PollOptionTableViewCell,
|
||||||
|
pollOption: PollOption,
|
||||||
|
itemAttribute: PollItem.Attribute
|
||||||
|
) {
|
||||||
|
cell.optionLabel.text = pollOption.title
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -155,7 +155,31 @@ extension StatusSection {
|
||||||
cell.statusView.statusMosaicImageView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0
|
cell.statusView.statusMosaicImageView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0
|
||||||
|
|
||||||
// set poll
|
// set poll
|
||||||
|
if let poll = (toot.reblog ?? toot).poll {
|
||||||
|
cell.statusView.statusPollTableView.isHidden = false
|
||||||
|
|
||||||
|
let managedObjectContext = toot.managedObjectContext!
|
||||||
|
cell.statusView.statusPollTableViewDataSource = PollSection.tableViewDiffableDataSource(
|
||||||
|
for: cell.statusView.statusPollTableView,
|
||||||
|
managedObjectContext: managedObjectContext
|
||||||
|
)
|
||||||
|
|
||||||
|
var snapshot = NSDiffableDataSourceSnapshot<PollSection, PollItem>()
|
||||||
|
snapshot.appendSections([.main])
|
||||||
|
let pollItems = poll.options
|
||||||
|
.sorted(by: { $0.index.intValue < $1.index.intValue })
|
||||||
|
.map { option -> PollItem in
|
||||||
|
let isVoted = (option.votedBy ?? Set()).map { $0.id }.contains(requestUserID)
|
||||||
|
let attribute = PollItem.Attribute(voted: isVoted)
|
||||||
|
let option = PollItem.opion(objectID: option.objectID, attribute: attribute)
|
||||||
|
return option
|
||||||
|
}
|
||||||
|
snapshot.appendItems(pollItems, toSection: .main)
|
||||||
|
cell.statusView.statusPollTableViewDataSource?.apply(snapshot, animatingDifferences: false, completion: nil)
|
||||||
|
// cell.statusView.statusPollTableView.layoutIfNeeded()
|
||||||
|
} else {
|
||||||
|
cell.statusView.statusPollTableView.isHidden = true
|
||||||
|
}
|
||||||
|
|
||||||
// toolbar
|
// toolbar
|
||||||
let replyCountTitle: String = {
|
let replyCountTitle: String = {
|
||||||
|
|
|
@ -152,6 +152,10 @@ extension HomeTimelineViewController {
|
||||||
self.context.apiService.backgroundManagedObjectContext.delete(toot)
|
self.context.apiService.backgroundManagedObjectContext.delete(toot)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.sink { _ in
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
.store(in: &self.disposeBag)
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
assertionFailure(error.localizedDescription)
|
assertionFailure(error.localizedDescription)
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,8 @@ protocol StatusViewDelegate: class {
|
||||||
|
|
||||||
final class StatusView: UIView {
|
final class StatusView: UIView {
|
||||||
|
|
||||||
|
var statusPollTableViewHeightObservation: NSKeyValueObservation?
|
||||||
|
|
||||||
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
|
||||||
|
@ -24,6 +26,7 @@ final class StatusView: UIView {
|
||||||
weak var delegate: StatusViewDelegate?
|
weak var delegate: StatusViewDelegate?
|
||||||
var isStatusTextSensitive = false
|
var isStatusTextSensitive = false
|
||||||
var statusPollTableViewDataSource: UITableViewDiffableDataSource<PollSection, PollItem>?
|
var statusPollTableViewDataSource: UITableViewDiffableDataSource<PollSection, PollItem>?
|
||||||
|
var statusPollTableViewHeightLaoutConstraint: NSLayoutConstraint!
|
||||||
|
|
||||||
let headerContainerStackView = UIStackView()
|
let headerContainerStackView = UIStackView()
|
||||||
|
|
||||||
|
@ -103,9 +106,11 @@ final class StatusView: UIView {
|
||||||
let statusMosaicImageView = MosaicImageViewContainer()
|
let statusMosaicImageView = MosaicImageViewContainer()
|
||||||
|
|
||||||
let statusPollTableView: UITableView = {
|
let statusPollTableView: UITableView = {
|
||||||
let tableView = UITableView()
|
let tableView = UITableView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
|
||||||
tableView.register(PollTableViewCell.self, forCellReuseIdentifier: String(describing: PollTableViewCell.self))
|
tableView.register(PollOptionTableViewCell.self, forCellReuseIdentifier: String(describing: PollOptionTableViewCell.self))
|
||||||
tableView.isScrollEnabled = false
|
tableView.isScrollEnabled = false
|
||||||
|
tableView.separatorStyle = .none
|
||||||
|
tableView.backgroundColor = .clear
|
||||||
return tableView
|
return tableView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
@ -144,6 +149,10 @@ final class StatusView: UIView {
|
||||||
drawContentWarningImageView()
|
drawContentWarningImageView()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
statusPollTableViewHeightObservation = nil
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -265,8 +274,23 @@ extension StatusView {
|
||||||
])
|
])
|
||||||
statusContentWarningContainerStackView.addArrangedSubview(contentWarningTitle)
|
statusContentWarningContainerStackView.addArrangedSubview(contentWarningTitle)
|
||||||
statusContentWarningContainerStackView.addArrangedSubview(contentWarningActionButton)
|
statusContentWarningContainerStackView.addArrangedSubview(contentWarningActionButton)
|
||||||
|
|
||||||
statusContainerStackView.addArrangedSubview(statusMosaicImageView)
|
statusContainerStackView.addArrangedSubview(statusMosaicImageView)
|
||||||
|
statusPollTableView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
statusContainerStackView.addArrangedSubview(statusPollTableView)
|
statusContainerStackView.addArrangedSubview(statusPollTableView)
|
||||||
|
statusPollTableViewHeightLaoutConstraint = statusPollTableView.heightAnchor.constraint(equalToConstant: 44.0).priority(.required - 1)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
statusPollTableViewHeightLaoutConstraint,
|
||||||
|
])
|
||||||
|
|
||||||
|
statusPollTableViewHeightObservation = statusPollTableView.observe(\.contentSize, options: .new, changeHandler: { [weak self] tableView, _ in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard self.statusPollTableView.contentSize.height != .zero else {
|
||||||
|
self.statusPollTableViewHeightLaoutConstraint.constant = 44
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.statusPollTableViewHeightLaoutConstraint.constant = self.statusPollTableView.contentSize.height
|
||||||
|
})
|
||||||
|
|
||||||
// action toolbar container
|
// action toolbar container
|
||||||
containerStackView.addArrangedSubview(actionToolbarContainer)
|
containerStackView.addArrangedSubview(actionToolbarContainer)
|
||||||
|
@ -322,14 +346,13 @@ extension StatusView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - AvatarConfigurableView
|
||||||
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 }
|
||||||
var configurableAvatarImageView: UIImageView? { return nil }
|
var configurableAvatarImageView: UIImageView? { return nil }
|
||||||
var configurableAvatarButton: UIButton? { return avatarButton }
|
var configurableAvatarButton: UIButton? { return avatarButton }
|
||||||
var configurableVerifiedBadgeImageView: UIImageView? { nil }
|
var configurableVerifiedBadgeImageView: UIImageView? { nil }
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if canImport(SwiftUI) && DEBUG
|
#if canImport(SwiftUI) && DEBUG
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
//
|
//
|
||||||
// PollTableViewCell.swift
|
// PollOptionTableViewCell.swift
|
||||||
// Mastodon
|
// Mastodon
|
||||||
//
|
//
|
||||||
// Created by MainasuK Cirno on 2021-2-25.
|
// Created by MainasuK Cirno on 2021-2-25.
|
||||||
|
@ -7,8 +7,11 @@
|
||||||
|
|
||||||
import UIKit
|
import UIKit
|
||||||
|
|
||||||
final class PollTableViewCell: UITableViewCell {
|
final class PollOptionTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
|
static let height: CGFloat = optionHeight + 2 * verticalMargin
|
||||||
|
static let optionHeight: CGFloat = 44
|
||||||
|
static let verticalMargin: CGFloat = 5
|
||||||
static let checkmarkImageSize = CGSize(width: 26, height: 26)
|
static let checkmarkImageSize = CGSize(width: 26, height: 26)
|
||||||
|
|
||||||
let roundedBackgroundView = UIView()
|
let roundedBackgroundView = UIView()
|
||||||
|
@ -57,9 +60,11 @@ final class PollTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PollTableViewCell {
|
extension PollOptionTableViewCell {
|
||||||
|
|
||||||
private func _init() {
|
private func _init() {
|
||||||
|
selectionStyle = .none
|
||||||
|
backgroundColor = .clear
|
||||||
roundedBackgroundView.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color
|
roundedBackgroundView.backgroundColor = Asset.Colors.Background.systemGroupedBackground.color
|
||||||
|
|
||||||
roundedBackgroundView.translatesAutoresizingMaskIntoConstraints = false
|
roundedBackgroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
@ -69,6 +74,7 @@ extension PollTableViewCell {
|
||||||
roundedBackgroundView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
|
roundedBackgroundView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
|
||||||
roundedBackgroundView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
|
roundedBackgroundView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor),
|
||||||
contentView.bottomAnchor.constraint(equalTo: roundedBackgroundView.bottomAnchor, constant: 5),
|
contentView.bottomAnchor.constraint(equalTo: roundedBackgroundView.bottomAnchor, constant: 5),
|
||||||
|
roundedBackgroundView.heightAnchor.constraint(equalToConstant: PollOptionTableViewCell.optionHeight).priority(.defaultHigh),
|
||||||
])
|
])
|
||||||
|
|
||||||
checkmarkBackgroundView.translatesAutoresizingMaskIntoConstraints = false
|
checkmarkBackgroundView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
@ -77,8 +83,8 @@ extension PollTableViewCell {
|
||||||
checkmarkBackgroundView.topAnchor.constraint(equalTo: roundedBackgroundView.topAnchor, constant: 9),
|
checkmarkBackgroundView.topAnchor.constraint(equalTo: roundedBackgroundView.topAnchor, constant: 9),
|
||||||
checkmarkBackgroundView.leadingAnchor.constraint(equalTo: roundedBackgroundView.leadingAnchor, constant: 9),
|
checkmarkBackgroundView.leadingAnchor.constraint(equalTo: roundedBackgroundView.leadingAnchor, constant: 9),
|
||||||
roundedBackgroundView.bottomAnchor.constraint(equalTo: checkmarkBackgroundView.bottomAnchor, constant: 9),
|
roundedBackgroundView.bottomAnchor.constraint(equalTo: checkmarkBackgroundView.bottomAnchor, constant: 9),
|
||||||
checkmarkBackgroundView.widthAnchor.constraint(equalToConstant: PollTableViewCell.checkmarkImageSize.width).priority(.defaultHigh),
|
checkmarkBackgroundView.widthAnchor.constraint(equalToConstant: PollOptionTableViewCell.checkmarkImageSize.width).priority(.defaultHigh),
|
||||||
checkmarkBackgroundView.heightAnchor.constraint(equalToConstant: PollTableViewCell.checkmarkImageSize.height).priority(.defaultHigh),
|
checkmarkBackgroundView.heightAnchor.constraint(equalToConstant: PollOptionTableViewCell.checkmarkImageSize.height).priority(.defaultHigh),
|
||||||
])
|
])
|
||||||
|
|
||||||
checkmarkImageView.translatesAutoresizingMaskIntoConstraints = false
|
checkmarkImageView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
@ -104,6 +110,8 @@ extension PollTableViewCell {
|
||||||
roundedBackgroundView.trailingAnchor.constraint(equalTo: optionPercentageLabel.trailingAnchor, constant: 18),
|
roundedBackgroundView.trailingAnchor.constraint(equalTo: optionPercentageLabel.trailingAnchor, constant: 18),
|
||||||
optionPercentageLabel.centerYAnchor.constraint(equalTo: roundedBackgroundView.centerYAnchor),
|
optionPercentageLabel.centerYAnchor.constraint(equalTo: roundedBackgroundView.centerYAnchor),
|
||||||
])
|
])
|
||||||
|
optionPercentageLabel.setContentHuggingPriority(.required - 1, for: .horizontal)
|
||||||
|
optionPercentageLabel.setContentCompressionResistancePriority(.required - 1, for: .horizontal)
|
||||||
|
|
||||||
configureCheckmark(state: .none)
|
configureCheckmark(state: .none)
|
||||||
}
|
}
|
||||||
|
@ -111,8 +119,12 @@ extension PollTableViewCell {
|
||||||
override func layoutSubviews() {
|
override func layoutSubviews() {
|
||||||
super.layoutSubviews()
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
updateCornerRadius()
|
||||||
|
}
|
||||||
|
|
||||||
|
private func updateCornerRadius() {
|
||||||
roundedBackgroundView.layer.masksToBounds = true
|
roundedBackgroundView.layer.masksToBounds = true
|
||||||
roundedBackgroundView.layer.cornerRadius = roundedBackgroundView.bounds.height * 0.5
|
roundedBackgroundView.layer.cornerRadius = PollOptionTableViewCell.optionHeight * 0.5
|
||||||
roundedBackgroundView.layer.cornerCurve = .circular
|
roundedBackgroundView.layer.cornerCurve = .circular
|
||||||
|
|
||||||
checkmarkBackgroundView.layer.masksToBounds = true
|
checkmarkBackgroundView.layer.masksToBounds = true
|
||||||
|
@ -122,7 +134,7 @@ extension PollTableViewCell {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension PollTableViewCell {
|
extension PollOptionTableViewCell {
|
||||||
|
|
||||||
enum CheckmarkState {
|
enum CheckmarkState {
|
||||||
case none
|
case none
|
||||||
|
@ -168,17 +180,17 @@ struct PollTableViewCell_Previews: PreviewProvider {
|
||||||
static var controls: some View {
|
static var controls: some View {
|
||||||
Group {
|
Group {
|
||||||
UIViewPreview() {
|
UIViewPreview() {
|
||||||
PollTableViewCell()
|
PollOptionTableViewCell()
|
||||||
}
|
}
|
||||||
.previewLayout(.fixed(width: 375, height: 44 + 10))
|
.previewLayout(.fixed(width: 375, height: 44 + 10))
|
||||||
UIViewPreview() {
|
UIViewPreview() {
|
||||||
let cell = PollTableViewCell()
|
let cell = PollOptionTableViewCell()
|
||||||
cell.configureCheckmark(state: .off)
|
cell.configureCheckmark(state: .off)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
.previewLayout(.fixed(width: 375, height: 44 + 10))
|
.previewLayout(.fixed(width: 375, height: 44 + 10))
|
||||||
UIViewPreview() {
|
UIViewPreview() {
|
||||||
let cell = PollTableViewCell()
|
let cell = PollOptionTableViewCell()
|
||||||
cell.configureCheckmark(state: .on)
|
cell.configureCheckmark(state: .on)
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
|
@ -10,7 +10,6 @@ import UIKit
|
||||||
import AVKit
|
import AVKit
|
||||||
import Combine
|
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)
|
func statusTableViewCell(_ cell: StatusTableViewCell, statusView: StatusView, contentWarningActionButtonPressed button: UIButton)
|
||||||
|
|
Loading…
Reference in New Issue