forked from zelo72/mastodon-ios
feat: add PollSection and PollItem for diffable data source
This commit is contained in:
parent
80954b0492
commit
8b63c2fda1
|
@ -109,6 +109,9 @@
|
||||||
DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB44384E25E8C1FA008912A2 /* CALayer.swift */; };
|
DB44384F25E8C1FA008912A2 /* CALayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB44384E25E8C1FA008912A2 /* CALayer.swift */; };
|
||||||
DB4481AD25EE155900BEFB67 /* Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481AC25EE155900BEFB67 /* Poll.swift */; };
|
DB4481AD25EE155900BEFB67 /* Poll.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481AC25EE155900BEFB67 /* Poll.swift */; };
|
||||||
DB4481B325EE16D000BEFB67 /* PollOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481B225EE16D000BEFB67 /* PollOption.swift */; };
|
DB4481B325EE16D000BEFB67 /* PollOption.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481B225EE16D000BEFB67 /* PollOption.swift */; };
|
||||||
|
DB4481B925EE289600BEFB67 /* UITableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481B825EE289600BEFB67 /* UITableView.swift */; };
|
||||||
|
DB4481C625EE2ADA00BEFB67 /* PollSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481C525EE2ADA00BEFB67 /* PollSection.swift */; };
|
||||||
|
DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4481CB25EE2AFE00BEFB67 /* PollItem.swift */; };
|
||||||
DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4563BC25E11A24004DA0B9 /* KeyboardResponderService.swift */; };
|
DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB4563BC25E11A24004DA0B9 /* KeyboardResponderService.swift */; };
|
||||||
DB45FAB625CA5485005A8AC7 /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */; };
|
DB45FAB625CA5485005A8AC7 /* UIAlertController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */; };
|
||||||
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */; };
|
DB45FAD725CA6C76005A8AC7 /* UIBarButtonItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */; };
|
||||||
|
@ -331,6 +334,9 @@
|
||||||
DB44384E25E8C1FA008912A2 /* CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CALayer.swift; sourceTree = "<group>"; };
|
DB44384E25E8C1FA008912A2 /* CALayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CALayer.swift; sourceTree = "<group>"; };
|
||||||
DB4481AC25EE155900BEFB67 /* Poll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Poll.swift; sourceTree = "<group>"; };
|
DB4481AC25EE155900BEFB67 /* Poll.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Poll.swift; sourceTree = "<group>"; };
|
||||||
DB4481B225EE16D000BEFB67 /* PollOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOption.swift; sourceTree = "<group>"; };
|
DB4481B225EE16D000BEFB67 /* PollOption.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOption.swift; sourceTree = "<group>"; };
|
||||||
|
DB4481B825EE289600BEFB67 /* UITableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = UITableView.swift; sourceTree = "<group>"; };
|
||||||
|
DB4481C525EE2ADA00BEFB67 /* PollSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollSection.swift; sourceTree = "<group>"; };
|
||||||
|
DB4481CB25EE2AFE00BEFB67 /* PollItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollItem.swift; sourceTree = "<group>"; };
|
||||||
DB4563BC25E11A24004DA0B9 /* KeyboardResponderService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardResponderService.swift; sourceTree = "<group>"; };
|
DB4563BC25E11A24004DA0B9 /* KeyboardResponderService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardResponderService.swift; sourceTree = "<group>"; };
|
||||||
DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = "<group>"; };
|
DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIAlertController.swift; sourceTree = "<group>"; };
|
||||||
DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIBarButtonItem.swift; sourceTree = "<group>"; };
|
DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIBarButtonItem.swift; sourceTree = "<group>"; };
|
||||||
|
@ -634,8 +640,8 @@
|
||||||
2D76319C25C151DE00929FB9 /* Diffiable */ = {
|
2D76319C25C151DE00929FB9 /* Diffiable */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2D7631B125C159E700929FB9 /* Item */,
|
|
||||||
2D76319D25C151F600929FB9 /* Section */,
|
2D76319D25C151F600929FB9 /* Section */,
|
||||||
|
2D7631B125C159E700929FB9 /* Item */,
|
||||||
);
|
);
|
||||||
path = Diffiable;
|
path = Diffiable;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -644,6 +650,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2D76319E25C1521200929FB9 /* StatusSection.swift */,
|
2D76319E25C1521200929FB9 /* StatusSection.swift */,
|
||||||
|
DB4481C525EE2ADA00BEFB67 /* PollSection.swift */,
|
||||||
);
|
);
|
||||||
path = Section;
|
path = Section;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -686,6 +693,7 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2D7631B225C159F700929FB9 /* Item.swift */,
|
2D7631B225C159F700929FB9 /* Item.swift */,
|
||||||
|
DB4481CB25EE2AFE00BEFB67 /* PollItem.swift */,
|
||||||
);
|
);
|
||||||
path = Item;
|
path = Item;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -1021,6 +1029,7 @@
|
||||||
DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */,
|
DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */,
|
||||||
2D42FF8E25C8228A004A627A /* UIButton.swift */,
|
2D42FF8E25C8228A004A627A /* UIButton.swift */,
|
||||||
DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */,
|
DB45FAD625CA6C76005A8AC7 /* UIBarButtonItem.swift */,
|
||||||
|
DB4481B825EE289600BEFB67 /* UITableView.swift */,
|
||||||
2D32EAB925CB9B0500C9ED86 /* UIView.swift */,
|
2D32EAB925CB9B0500C9ED86 /* UIView.swift */,
|
||||||
0FAA101B25E10E760017CCDE /* UIFont.swift */,
|
0FAA101B25E10E760017CCDE /* UIFont.swift */,
|
||||||
2D650FAA25ECDC9300851B58 /* Mastodon+Entidy+ErrorDetailReason.swift */,
|
2D650FAA25ECDC9300851B58 /* Mastodon+Entidy+ErrorDetailReason.swift */,
|
||||||
|
@ -1476,7 +1485,9 @@
|
||||||
DB45FAE325CA7181005A8AC7 /* MastodonUser.swift in Sources */,
|
DB45FAE325CA7181005A8AC7 /* MastodonUser.swift in Sources */,
|
||||||
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */,
|
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */,
|
||||||
2D69D00A25CAA00300C3A1B2 /* APIService+CoreData+Toot.swift in Sources */,
|
2D69D00A25CAA00300C3A1B2 /* APIService+CoreData+Toot.swift in Sources */,
|
||||||
|
DB4481C625EE2ADA00BEFB67 /* PollSection.swift in Sources */,
|
||||||
2D939AB525EDD8A90076FA61 /* String.swift in Sources */,
|
2D939AB525EDD8A90076FA61 /* String.swift in Sources */,
|
||||||
|
DB4481B925EE289600BEFB67 /* UITableView.swift in Sources */,
|
||||||
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */,
|
0FAA101C25E10E760017CCDE /* UIFont.swift in Sources */,
|
||||||
2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */,
|
2D38F1D525CD465300561493 /* HomeTimelineViewController.swift in Sources */,
|
||||||
DB98338825C945ED00AD9700 /* Assets.swift in Sources */,
|
DB98338825C945ED00AD9700 /* Assets.swift in Sources */,
|
||||||
|
@ -1501,6 +1512,7 @@
|
||||||
2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */,
|
2D46976425C2A71500CF4AA9 /* UIIamge.swift in Sources */,
|
||||||
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
|
DB8AF55D25C138B7002E6C99 /* UIViewController.swift in Sources */,
|
||||||
2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */,
|
2D3F9E0425DFA133004262D9 /* UITapGestureRecognizer.swift in Sources */,
|
||||||
|
DB4481CC25EE2AFE00BEFB67 /* PollItem.swift in Sources */,
|
||||||
DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */,
|
DB4563BD25E11A24004DA0B9 /* KeyboardResponderService.swift in Sources */,
|
||||||
DB5086BE25CC0D9900C2C187 /* SplashPreference.swift in Sources */,
|
DB5086BE25CC0D9900C2C187 /* SplashPreference.swift in Sources */,
|
||||||
2DF75BA125D0E29D00694EC8 /* StatusProvider+TimelinePostTableViewCellDelegate.swift in Sources */,
|
2DF75BA125D0E29D00694EC8 /* StatusProvider+TimelinePostTableViewCellDelegate.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
//
|
||||||
|
// PollItem.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021-3-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
enum PollItem {
|
||||||
|
case pollOpion(objectID: NSManagedObjectID, attribute: Attribute)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension PollItem {
|
||||||
|
class Attribute: Hashable {
|
||||||
|
var voted: Bool = false
|
||||||
|
|
||||||
|
static func == (lhs: PollItem.Attribute, rhs: PollItem.Attribute) -> Bool {
|
||||||
|
return lhs.voted == rhs.voted
|
||||||
|
}
|
||||||
|
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
hasher.combine(voted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PollItem: Equatable {
|
||||||
|
static func == (lhs: PollItem, rhs: PollItem) -> Bool {
|
||||||
|
switch (lhs, rhs) {
|
||||||
|
case (.pollOpion(let objectIDLeft, _), .pollOpion(let objectIDRight, _)):
|
||||||
|
return objectIDLeft == objectIDRight
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension PollItem: Hashable {
|
||||||
|
func hash(into hasher: inout Hasher) {
|
||||||
|
switch self {
|
||||||
|
case .pollOpion(let objectID, _):
|
||||||
|
hasher.combine(objectID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
//
|
||||||
|
// PollSection.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021-3-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import CoreData
|
||||||
|
import CoreDataStack
|
||||||
|
|
||||||
|
enum PollSection {
|
||||||
|
case main
|
||||||
|
}
|
||||||
|
|
||||||
|
extension PollSection {
|
||||||
|
static func tableViewDiffableDataSource(
|
||||||
|
for tableView: UITableView,
|
||||||
|
managedObjectContext: NSManagedObjectContext
|
||||||
|
) -> UITableViewDiffableDataSource<PollSection, PollItem> {
|
||||||
|
return UITableViewDiffableDataSource<PollSection, PollItem>(tableView: tableView) { tableView, indexPath, item -> UITableViewCell? in
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -153,6 +153,9 @@ extension StatusSection {
|
||||||
let isStatusSensitive = statusContentWarningAttribute?.isStatusSensitive ?? (toot.reblog ?? toot).sensitive
|
let isStatusSensitive = statusContentWarningAttribute?.isStatusSensitive ?? (toot.reblog ?? toot).sensitive
|
||||||
cell.statusView.statusMosaicImageView.blurVisualEffectView.effect = isStatusSensitive ? MosaicImageViewContainer.blurVisualEffect : nil
|
cell.statusView.statusMosaicImageView.blurVisualEffectView.effect = isStatusSensitive ? MosaicImageViewContainer.blurVisualEffect : nil
|
||||||
cell.statusView.statusMosaicImageView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0
|
cell.statusView.statusMosaicImageView.vibrancyVisualEffectView.alpha = isStatusSensitive ? 1.0 : 0.0
|
||||||
|
|
||||||
|
// set poll
|
||||||
|
|
||||||
|
|
||||||
// toolbar
|
// toolbar
|
||||||
let replyCountTitle: String = {
|
let replyCountTitle: String = {
|
||||||
|
|
|
@ -0,0 +1,55 @@
|
||||||
|
//
|
||||||
|
// UITableView.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by Cirno MainasuK on 2021-3-2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
extension UITableView {
|
||||||
|
|
||||||
|
// static let groupedTableViewPaddingHeaderViewHeight: CGFloat = 16
|
||||||
|
// static var groupedTableViewPaddingHeaderView: UIView {
|
||||||
|
// return UIView(frame: CGRect(x: 0, y: 0, width: 100, height: groupedTableViewPaddingHeaderViewHeight))
|
||||||
|
// }
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension UITableView {
|
||||||
|
|
||||||
|
func deselectRow(with transitionCoordinator: UIViewControllerTransitionCoordinator?, animated: Bool) {
|
||||||
|
guard let indexPathForSelectedRow = indexPathForSelectedRow else { return }
|
||||||
|
|
||||||
|
guard let transitionCoordinator = transitionCoordinator else {
|
||||||
|
deselectRow(at: indexPathForSelectedRow, animated: animated)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
transitionCoordinator.animate(alongsideTransition: { _ in
|
||||||
|
self.deselectRow(at: indexPathForSelectedRow, animated: animated)
|
||||||
|
}, completion: { context in
|
||||||
|
if context.isCancelled {
|
||||||
|
self.selectRow(at: indexPathForSelectedRow, animated: animated, scrollPosition: .none)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func blinkRow(at indexPath: IndexPath) {
|
||||||
|
DispatchQueue.main.asyncAfter(wallDeadline: .now() + 1) { [weak self] in
|
||||||
|
guard let self = self else { return }
|
||||||
|
guard let cell = self.cellForRow(at: indexPath) else { return }
|
||||||
|
let backgroundColor = cell.backgroundColor
|
||||||
|
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
cell.backgroundColor = Asset.Colors.Label.highlight.color.withAlphaComponent(0.5)
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
cell.backgroundColor = backgroundColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -19,6 +19,7 @@ extension HomeTimelineViewController {
|
||||||
identifier: nil,
|
identifier: nil,
|
||||||
options: .displayInline,
|
options: .displayInline,
|
||||||
children: [
|
children: [
|
||||||
|
moveMenu,
|
||||||
dropMenu,
|
dropMenu,
|
||||||
UIAction(title: "Show Public Timeline", image: UIImage(systemName: "list.dash"), attributes: []) { [weak self] action in
|
UIAction(title: "Show Public Timeline", image: UIImage(systemName: "list.dash"), attributes: []) { [weak self] action in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
@ -33,6 +34,41 @@ extension HomeTimelineViewController {
|
||||||
return menu
|
return menu
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var moveMenu: UIMenu {
|
||||||
|
return UIMenu(
|
||||||
|
title: "Move to…",
|
||||||
|
image: UIImage(systemName: "arrow.forward.circle"),
|
||||||
|
identifier: nil,
|
||||||
|
options: [],
|
||||||
|
children: [
|
||||||
|
UIAction(title: "First Gap", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.moveToTopGapAction(action)
|
||||||
|
}),
|
||||||
|
UIAction(title: "First Poll Toot", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
guard let self = self else { return }
|
||||||
|
self.moveToFirstPollToot(action)
|
||||||
|
}),
|
||||||
|
// UIAction(title: "First Reply Toot", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
// guard let self = self else { return }
|
||||||
|
// self.moveToFirstReplyToot(action)
|
||||||
|
// }),
|
||||||
|
// UIAction(title: "First Reply Reblog", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
// guard let self = self else { return }
|
||||||
|
// self.moveToFirstReplyReblog(action)
|
||||||
|
// }),
|
||||||
|
// UIAction(title: "First Video Toot", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
// guard let self = self else { return }
|
||||||
|
// self.moveToFirstVideoToot(action)
|
||||||
|
// }),
|
||||||
|
// UIAction(title: "First GIF Toot", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
|
// guard let self = self else { return }
|
||||||
|
// self.moveToFirstGIFToot(action)
|
||||||
|
// }),
|
||||||
|
]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
var dropMenu: UIMenu {
|
var dropMenu: UIMenu {
|
||||||
return UIMenu(
|
return UIMenu(
|
||||||
title: "Drop…",
|
title: "Drop…",
|
||||||
|
@ -40,9 +76,9 @@ extension HomeTimelineViewController {
|
||||||
identifier: nil,
|
identifier: nil,
|
||||||
options: [],
|
options: [],
|
||||||
children: [50, 100, 150, 200, 250, 300].map { count in
|
children: [50, 100, 150, 200, 250, 300].map { count in
|
||||||
UIAction(title: "Drop Recent \(count) Tweets", image: nil, attributes: [], handler: { [weak self] action in
|
UIAction(title: "Drop Recent \(count) Toots", image: nil, attributes: [], handler: { [weak self] action in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.dropRecentTweetsAction(action, count: count)
|
self.dropRecentTootsAction(action, count: count)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
@ -51,7 +87,42 @@ extension HomeTimelineViewController {
|
||||||
|
|
||||||
extension HomeTimelineViewController {
|
extension HomeTimelineViewController {
|
||||||
|
|
||||||
@objc private func dropRecentTweetsAction(_ sender: UIAction, count: Int) {
|
@objc private func moveToTopGapAction(_ sender: UIAction) {
|
||||||
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
|
let snapshotTransitioning = diffableDataSource.snapshot()
|
||||||
|
let item = snapshotTransitioning.itemIdentifiers.first(where: { item in
|
||||||
|
switch item {
|
||||||
|
case .homeMiddleLoader: return true
|
||||||
|
default: return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) {
|
||||||
|
tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func moveToFirstPollToot(_ sender: UIAction) {
|
||||||
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
|
let snapshotTransitioning = diffableDataSource.snapshot()
|
||||||
|
let item = snapshotTransitioning.itemIdentifiers.first(where: { item in
|
||||||
|
switch item {
|
||||||
|
case .homeTimelineIndex(let objectID, _):
|
||||||
|
let homeTimelineIndex = viewModel.fetchedResultsController.managedObjectContext.object(with: objectID) as! HomeTimelineIndex
|
||||||
|
let toot = homeTimelineIndex.toot.reblog ?? homeTimelineIndex.toot
|
||||||
|
return toot.poll != nil
|
||||||
|
default:
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if let targetItem = item, let index = snapshotTransitioning.indexOfItem(targetItem) {
|
||||||
|
tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true)
|
||||||
|
tableView.blinkRow(at: IndexPath(row: index, section: 0))
|
||||||
|
} else {
|
||||||
|
print("Not found poll toot")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func dropRecentTootsAction(_ sender: UIAction, count: Int) {
|
||||||
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
guard let diffableDataSource = viewModel.diffableDataSource else { return }
|
||||||
let snapshotTransitioning = diffableDataSource.snapshot()
|
let snapshotTransitioning = diffableDataSource.snapshot()
|
||||||
|
|
||||||
|
|
|
@ -110,10 +110,10 @@ final class HomeTimelineViewModel: NSObject {
|
||||||
context.authenticationService.activeMastodonAuthentication
|
context.authenticationService.activeMastodonAuthentication
|
||||||
.sink { [weak self] activeMastodonAuthentication in
|
.sink { [weak self] activeMastodonAuthentication in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
guard let twitterAuthentication = activeMastodonAuthentication else { return }
|
guard let mastodonAuthentication = activeMastodonAuthentication else { return }
|
||||||
let activeTwitterUserID = twitterAuthentication.userID
|
let activeMastodonUserID = mastodonAuthentication.userID
|
||||||
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
|
let predicate = NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||||
HomeTimelineIndex.predicate(userID: activeTwitterUserID),
|
HomeTimelineIndex.predicate(userID: activeMastodonUserID),
|
||||||
HomeTimelineIndex.notDeleted()
|
HomeTimelineIndex.notDeleted()
|
||||||
])
|
])
|
||||||
self.timelinePredicate.value = predicate
|
self.timelinePredicate.value = predicate
|
||||||
|
|
|
@ -23,6 +23,7 @@ final class StatusView: UIView {
|
||||||
|
|
||||||
weak var delegate: StatusViewDelegate?
|
weak var delegate: StatusViewDelegate?
|
||||||
var isStatusTextSensitive = false
|
var isStatusTextSensitive = false
|
||||||
|
var statusPollTableViewDataSource: UITableViewDiffableDataSource<PollSection, PollItem>?
|
||||||
|
|
||||||
let headerContainerStackView = UIStackView()
|
let headerContainerStackView = UIStackView()
|
||||||
|
|
||||||
|
@ -101,6 +102,13 @@ final class StatusView: UIView {
|
||||||
}()
|
}()
|
||||||
let statusMosaicImageView = MosaicImageViewContainer()
|
let statusMosaicImageView = MosaicImageViewContainer()
|
||||||
|
|
||||||
|
let statusPollTableView: UITableView = {
|
||||||
|
let tableView = UITableView()
|
||||||
|
tableView.register(PollTableViewCell.self, forCellReuseIdentifier: String(describing: PollTableViewCell.self))
|
||||||
|
tableView.isScrollEnabled = false
|
||||||
|
return tableView
|
||||||
|
}()
|
||||||
|
|
||||||
// do not use visual effect view due to we blur text only without background
|
// do not use visual effect view due to we blur text only without background
|
||||||
let contentWarningBlurContentImageView: UIImageView = {
|
let contentWarningBlurContentImageView: UIImageView = {
|
||||||
let imageView = UIImageView()
|
let imageView = UIImageView()
|
||||||
|
@ -222,7 +230,7 @@ extension StatusView {
|
||||||
subtitleContainerStackView.axis = .horizontal
|
subtitleContainerStackView.axis = .horizontal
|
||||||
subtitleContainerStackView.addArrangedSubview(usernameLabel)
|
subtitleContainerStackView.addArrangedSubview(usernameLabel)
|
||||||
|
|
||||||
// status container: [status | image / video | audio]
|
// status container: [status | image / video | audio | poll]
|
||||||
containerStackView.addArrangedSubview(statusContainerStackView)
|
containerStackView.addArrangedSubview(statusContainerStackView)
|
||||||
statusContainerStackView.axis = .vertical
|
statusContainerStackView.axis = .vertical
|
||||||
statusContainerStackView.spacing = 10
|
statusContainerStackView.spacing = 10
|
||||||
|
@ -258,7 +266,7 @@ extension StatusView {
|
||||||
statusContentWarningContainerStackView.addArrangedSubview(contentWarningTitle)
|
statusContentWarningContainerStackView.addArrangedSubview(contentWarningTitle)
|
||||||
statusContentWarningContainerStackView.addArrangedSubview(contentWarningActionButton)
|
statusContentWarningContainerStackView.addArrangedSubview(contentWarningActionButton)
|
||||||
statusContainerStackView.addArrangedSubview(statusMosaicImageView)
|
statusContainerStackView.addArrangedSubview(statusMosaicImageView)
|
||||||
|
statusContainerStackView.addArrangedSubview(statusPollTableView)
|
||||||
|
|
||||||
// action toolbar container
|
// action toolbar container
|
||||||
containerStackView.addArrangedSubview(actionToolbarContainer)
|
containerStackView.addArrangedSubview(actionToolbarContainer)
|
||||||
|
@ -266,6 +274,8 @@ extension StatusView {
|
||||||
|
|
||||||
headerContainerStackView.isHidden = true
|
headerContainerStackView.isHidden = true
|
||||||
statusMosaicImageView.isHidden = true
|
statusMosaicImageView.isHidden = true
|
||||||
|
statusPollTableView.isHidden = true
|
||||||
|
|
||||||
contentWarningBlurContentImageView.isHidden = true
|
contentWarningBlurContentImageView.isHidden = true
|
||||||
statusContentWarningContainerStackView.isHidden = true
|
statusContentWarningContainerStackView.isHidden = true
|
||||||
statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false
|
statusContentWarningContainerStackViewBottomLayoutConstraint.isActive = false
|
||||||
|
|
|
@ -33,6 +33,7 @@ final class StatusTableViewCell: UITableViewCell {
|
||||||
override func prepareForReuse() {
|
override func prepareForReuse() {
|
||||||
super.prepareForReuse()
|
super.prepareForReuse()
|
||||||
statusView.isStatusTextSensitive = false
|
statusView.isStatusTextSensitive = false
|
||||||
|
statusView.statusPollTableView.dataSource = nil
|
||||||
statusView.cleanUpContentWarning()
|
statusView.cleanUpContentWarning()
|
||||||
disposeBag.removeAll()
|
disposeBag.removeAll()
|
||||||
observations.removeAll()
|
observations.removeAll()
|
||||||
|
|
Loading…
Reference in New Issue