From 55662cf2dc741cf8bae7789d554aae285a2c74d4 Mon Sep 17 00:00:00 2001 From: Dwayne Harris Date: Sat, 10 Nov 2018 15:00:16 -0800 Subject: [PATCH] Development --- .gitmodules | 3 + Frameworks/FLAnimatedImage | 1 + elpha-ios.xcodeproj/project.pbxproj | 65 ++++++++++- .../AbstractStatusTableViewController.swift | 65 +++++++++++ elpha-ios/AccountTableViewController.swift | 109 +++++++----------- elpha-ios/AuthenticateViewController.swift | 3 +- elpha-ios/Base.lproj/Main.storyboard | 8 +- elpha-ios/CellHeightManager.swift | 39 +++++++ elpha-ios/StatusTableViewController.swift | 63 +++------- elpha-ios/StatusView.swift | 14 +++ elpha-ios/TimelineTableViewController.swift | 109 +++++++----------- elpha-ios/UITextViewFixed.swift | 5 +- 12 files changed, 291 insertions(+), 193 deletions(-) create mode 160000 Frameworks/FLAnimatedImage create mode 100644 elpha-ios/AbstractStatusTableViewController.swift create mode 100644 elpha-ios/CellHeightManager.swift diff --git a/.gitmodules b/.gitmodules index 6d9947b..250b3d0 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "Frameworks/AlamofireNetworkActivityIndicator"] path = Frameworks/AlamofireNetworkActivityIndicator url = https://github.com/Alamofire/AlamofireNetworkActivityIndicator.git +[submodule "Frameworks/FLAnimatedImage"] + path = Frameworks/FLAnimatedImage + url = https://github.com/Flipboard/FLAnimatedImage.git diff --git a/Frameworks/FLAnimatedImage b/Frameworks/FLAnimatedImage new file mode 160000 index 0000000..16fe62b --- /dev/null +++ b/Frameworks/FLAnimatedImage @@ -0,0 +1 @@ +Subproject commit 16fe62b540f63294cfdfdcd04ebcd9e2c093819c diff --git a/elpha-ios.xcodeproj/project.pbxproj b/elpha-ios.xcodeproj/project.pbxproj index 0c4b654..8f6e90d 100644 --- a/elpha-ios.xcodeproj/project.pbxproj +++ b/elpha-ios.xcodeproj/project.pbxproj @@ -18,6 +18,10 @@ 152734D22186DC74003DB3C8 /* TimelinesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152734D12186DC74003DB3C8 /* TimelinesViewController.swift */; }; 152FB0F8218ADC1A001D6574 /* AttachmentPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152FB0F7218ADC1A001D6574 /* AttachmentPageViewController.swift */; }; 152FB0FA218ADDD0001D6574 /* AttachmentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152FB0F9218ADDD0001D6574 /* AttachmentViewController.swift */; }; + 152FBCD2219682E80079B3E8 /* AbstractStatusTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152FBCD1219682E80079B3E8 /* AbstractStatusTableViewController.swift */; }; + 152FBCE621978C4A0079B3E8 /* CellHeightManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152FBCE521978C4A0079B3E8 /* CellHeightManager.swift */; }; + 152FBCED219799FC0079B3E8 /* FLAnimatedImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 152FBCEC219799E50079B3E8 /* FLAnimatedImage.framework */; }; + 152FBCEE219799FC0079B3E8 /* FLAnimatedImage.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 152FBCEC219799E50079B3E8 /* FLAnimatedImage.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1539509121894A38009BA6E7 /* AlertManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1539509021894A38009BA6E7 /* AlertManager.swift */; }; 156FF015217289380074D9CA /* AccountTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156FF014217289380074D9CA /* AccountTableViewCell.swift */; }; 156FF0312174797E0074D9CA /* StatusTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156FF0302174797E0074D9CA /* StatusTableViewController.swift */; }; @@ -150,6 +154,20 @@ remoteGlobalIDString = 4CB928381C66E1A600CE5F08; remoteInfo = AlamofireNetworkActivityIndicator; }; + 152FBCEB219799E50079B3E8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 152FBCE7219799E50079B3E8 /* FLAnimatedImage.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 92C9BC0C1B199DC500D79B06; + remoteInfo = FLAnimatedImage; + }; + 152FBCEF219799FC0079B3E8 /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 152FBCE7219799E50079B3E8 /* FLAnimatedImage.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 92C9BC0B1B199DC500D79B06; + remoteInfo = FLAnimatedImage; + }; 157405C2215890BC00EEAAEB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */; @@ -209,6 +227,7 @@ dstSubfolderSpec = 10; files = ( 151AD4D9216899AD00F07403 /* AlamofireImage.framework in Embed Frameworks */, + 152FBCEE219799FC0079B3E8 /* FLAnimatedImage.framework in Embed Frameworks */, 151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */, 1522EC802193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Embed Frameworks */, ); @@ -227,6 +246,9 @@ 152734D12186DC74003DB3C8 /* TimelinesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesViewController.swift; sourceTree = ""; }; 152FB0F7218ADC1A001D6574 /* AttachmentPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentPageViewController.swift; sourceTree = ""; }; 152FB0F9218ADDD0001D6574 /* AttachmentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AttachmentViewController.swift; sourceTree = ""; }; + 152FBCD1219682E80079B3E8 /* AbstractStatusTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AbstractStatusTableViewController.swift; sourceTree = ""; }; + 152FBCE521978C4A0079B3E8 /* CellHeightManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CellHeightManager.swift; sourceTree = ""; }; + 152FBCE7219799E50079B3E8 /* FLAnimatedImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = FLAnimatedImage.xcodeproj; path = Frameworks/FLAnimatedImage/FLAnimatedImage.xcodeproj; sourceTree = ""; }; 1539509021894A38009BA6E7 /* AlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertManager.swift; sourceTree = ""; }; 156FF014217289380074D9CA /* AccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = ""; }; 156FF0302174797E0074D9CA /* StatusTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewController.swift; sourceTree = ""; }; @@ -274,6 +296,7 @@ buildActionMask = 2147483647; files = ( 15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */, + 152FBCED219799FC0079B3E8 /* FLAnimatedImage.framework in Frameworks */, 157405D1215890D700EEAAEB /* Alamofire.framework in Frameworks */, 1522EC7F2193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Frameworks */, ); @@ -312,6 +335,7 @@ 1539509021894A38009BA6E7 /* AlertManager.swift */, 1574148C2169AD0100C841BD /* AttachmentManager.swift */, 15960E7B213272CD00C38CE9 /* AuthenticationManager.swift */, + 152FBCE521978C4A0079B3E8 /* CellHeightManager.swift */, 15A79B42215EB959007A326E /* CoreDataManager.swift */, 157405B32151A93E00EEAAEB /* InstancesDataManager.swift */, 15F998342162C0E8009E58DA /* MastodonDataManager.swift */, @@ -362,6 +386,22 @@ name = Products; sourceTree = ""; }; + 152FBCE4219789450079B3E8 /* Abstract View Controllers */ = { + isa = PBXGroup; + children = ( + 152FBCD1219682E80079B3E8 /* AbstractStatusTableViewController.swift */, + ); + name = "Abstract View Controllers"; + sourceTree = ""; + }; + 152FBCE8219799E50079B3E8 /* Products */ = { + isa = PBXGroup; + children = ( + 152FBCEC219799E50079B3E8 /* FLAnimatedImage.framework */, + ); + name = Products; + sourceTree = ""; + }; 156FF05621779C140074D9CA /* API */ = { isa = PBXGroup; children = ( @@ -399,6 +439,7 @@ 157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */, 1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */, 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */, + 152FBCE7219799E50079B3E8 /* FLAnimatedImage.xcodeproj */, 15960E59213145E100C38CE9 /* elpha-ios */, 15960E58213145E100C38CE9 /* Products */, 157405D0215890D700EEAAEB /* Frameworks */, @@ -428,6 +469,7 @@ 151AD4AC2166DD0200F07403 /* Managers */, 151AD4AD2166DD1B00F07403 /* Reusable Views */, 151AD4AB2166DCEE00F07403 /* Storyboards */, + 152FBCE4219789450079B3E8 /* Abstract View Controllers */, 15960E782132383600C38CE9 /* View Controllers */, 151AD4AE2166DD3500F07403 /* Views */, ); @@ -480,6 +522,7 @@ 151AD4DB216899AD00F07403 /* PBXTargetDependency */, 151AD4E821689A0F00F07403 /* PBXTargetDependency */, 1522EC822193EBCB0082C3FA /* PBXTargetDependency */, + 152FBCF0219799FC0079B3E8 /* PBXTargetDependency */, ); name = "elpha-ios"; productName = "elpha-ios"; @@ -526,6 +569,10 @@ ProductGroup = 1522EC762193EBA10082C3FA /* Products */; ProjectRef = 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */; }, + { + ProductGroup = 152FBCE8219799E50079B3E8 /* Products */; + ProjectRef = 152FBCE7219799E50079B3E8 /* FLAnimatedImage.xcodeproj */; + }, ); projectRoot = ""; targets = ( @@ -605,6 +652,13 @@ remoteRef = 1522EC7D2193EBA10082C3FA /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 152FBCEC219799E50079B3E8 /* FLAnimatedImage.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = FLAnimatedImage.framework; + remoteRef = 152FBCEB219799E50079B3E8 /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 157405C3215890BC00EEAAEB /* Alamofire.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; @@ -707,11 +761,13 @@ 15960E7321322BC700C38CE9 /* KeychainItemAccessibility.swift in Sources */, 156FF051217683270074D9CA /* StatusTableViewCell.swift in Sources */, 159026D02163069600D362DD /* Date+TimeAgo.swift in Sources */, + 152FBCD2219682E80079B3E8 /* AbstractStatusTableViewController.swift in Sources */, 15A79B43215EB959007A326E /* CoreDataManager.swift in Sources */, 15BB72AB2171A8D4002F1FA4 /* TimelinesTableViewCell.swift in Sources */, 1574148D2169AD0100C841BD /* AttachmentManager.swift in Sources */, 156FF015217289380074D9CA /* AccountTableViewCell.swift in Sources */, 15960E822136668500C38CE9 /* TimelinesNavigationController.swift in Sources */, + 152FBCE621978C4A0079B3E8 /* CellHeightManager.swift in Sources */, 156FF04F2175CDBC0074D9CA /* MainStatusTableViewCell.swift in Sources */, 159026AE2162CF5600D362DD /* TimelineTableViewCell.swift in Sources */, ); @@ -735,6 +791,11 @@ name = AlamofireNetworkActivityIndicator; targetProxy = 1522EC812193EBCB0082C3FA /* PBXContainerItemProxy */; }; + 152FBCF0219799FC0079B3E8 /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = FLAnimatedImage; + targetProxy = 152FBCEF219799FC0079B3E8 /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -878,7 +939,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; CODE_SIGN_STYLE = Manual; - DEVELOPMENT_TEAM = ""; + DEVELOPMENT_TEAM = 4HV9QP2X8X; INFOPLIST_FILE = "elpha-ios/Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( @@ -887,7 +948,7 @@ ); PRODUCT_BUNDLE_IDENTIFIER = "xyz.elpha.elpha-ios"; PRODUCT_NAME = "$(TARGET_NAME)"; - PROVISIONING_PROFILE_SPECIFIER = ""; + PROVISIONING_PROFILE_SPECIFIER = Elpha; SWIFT_VERSION = 4.2; TARGETED_DEVICE_FAMILY = 1; }; diff --git a/elpha-ios/AbstractStatusTableViewController.swift b/elpha-ios/AbstractStatusTableViewController.swift new file mode 100644 index 0000000..b27cd37 --- /dev/null +++ b/elpha-ios/AbstractStatusTableViewController.swift @@ -0,0 +1,65 @@ +// +// ELStatusTableViewController.swift +// elpha-ios +// +// Created by Dwayne Harris on 11/9/18. +// Copyright © 2018 Elpha. All rights reserved. +// + +import UIKit +import SafariServices + +class AbstractStatusTableViewController: UITableViewController, StatusViewDelegate { + let fetchLimit = 20 + var loading: Bool = false + var currentPaginationContext: String = "" + var cellHeightsDictionary: NSMutableDictionary = [:] + + func accountTapped(account: AccountMO) { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + + if let controller = storyboard.instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController { + controller.account = account + self.navigationController?.pushViewController(controller, animated: true) + } + } + + func statusTapped(status: StatusMO) { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + + if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController { + controller.status = status + self.navigationController?.pushViewController(controller, animated: true) + } + } + + func loadMoreTapped(status: StatusMO, direction: PaginationDirection) { + + } + + func attachmentTapped(status: StatusMO, index: Int) { + let storyboard = UIStoryboard(name: "Main", bundle: nil) + + if let controller = storyboard.instantiateViewController(withIdentifier: "AttachmentPageViewController") as? AttachmentPageViewController { + controller.status = status + controller.attachmentIndex = index + + present(controller, animated: false) + } + } + + func urlTapped(url: URL) { + let controller = SFSafariViewController(url: url) + controller.delegate = self + controller.dismissButtonStyle = .done + controller.preferredControlTintColor = UIColor(named: "Primary") + + present(controller, animated: true) + } +} + +extension AbstractStatusTableViewController: SFSafariViewControllerDelegate { + func safariViewControllerDidFinish(_ controller: SFSafariViewController) { + controller.dismiss(animated: true) + } +} diff --git a/elpha-ios/AccountTableViewController.swift b/elpha-ios/AccountTableViewController.swift index 061d968..bf1f09b 100644 --- a/elpha-ios/AccountTableViewController.swift +++ b/elpha-ios/AccountTableViewController.swift @@ -11,7 +11,7 @@ import CoreData import UIKit import SafariServices -class AccountTableViewController: UITableViewController { +class AccountTableViewController: AbstractStatusTableViewController { @IBOutlet var headerView: UIView! @IBOutlet var headerImageView: UIImageView! @IBOutlet var avatarImageView: UIImageView! @@ -23,21 +23,25 @@ class AccountTableViewController: UITableViewController { @IBOutlet var followersLabel: UILabel! @IBOutlet var statusTypeSegmentedControl: UISegmentedControl! - let fetchLimit = 20 var fetchedResultsController: NSFetchedResultsController? = nil var account: AccountMO? = nil - var loading: Bool = false - var currentPaginationContext: String { - guard let account = self.account else { - return "" + override var currentPaginationContext: String { + get { + guard let account = self.account else { + return "" + } + + switch statusTypeSegmentedControl.selectedSegmentIndex { + case 3: + return "timeline:favorites" + case let index: + return "account:\(account.acct!):\(index)" + } } - switch statusTypeSegmentedControl.selectedSegmentIndex { - case 3: - return "timeline:favorites" - case let index: - return "account:\(account.acct!):\(index)" + set { + } } @@ -113,6 +117,20 @@ class AccountTableViewController: UITableViewController { } } + override func loadMoreTapped(status: StatusMO, direction: PaginationDirection) { + if let markers = status.markers { + markers.forEach { marker in + if marker.context == self.currentPaginationContext && marker.item.direction == direction { + fetchStatuses(withPagination: marker.item) { error in + if error != nil { + AlertManager.shared.show(message: error!.localizedDescription, category: .error) + } + } + } + } + } + } + @objc func fetch() { fetchStatuses { error in if error != nil { @@ -260,6 +278,16 @@ extension AccountTableViewController: NSFetchedResultsControllerDelegate { return 1 } + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if let cell = cell as? AccountTableViewCell { + CellHeightManager.set(status: cell.statusView.status, height: cell.frame.size.height) + } + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return CellHeightManager.get(status: fetchedResultsController?.object(at: indexPath)) + } + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { guard let count = fetchedResultsController?.fetchedObjects?.count else { return 0 @@ -321,62 +349,3 @@ extension AccountTableViewController: NSFetchedResultsControllerDelegate { return cell } } - -extension AccountTableViewController: StatusViewDelegate { - func accountTapped(account: AccountMO) { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - - if let controller = storyboard.instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController { - controller.account = account - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func statusTapped(status: StatusMO) { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - - if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController { - controller.status = status - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func loadMoreTapped(status: StatusMO, direction: PaginationDirection) { - if let markers = status.markers { - markers.forEach { marker in - if marker.context == self.currentPaginationContext && marker.item.direction == direction { - fetchStatuses(withPagination: marker.item) { error in - if error != nil { - AlertManager.shared.show(message: error!.localizedDescription, category: .error) - } - } - } - } - } - } - - func attachmentTapped(status: StatusMO, index: Int) { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AttachmentPageViewController") as? AttachmentPageViewController { - controller.status = status - controller.attachmentIndex = index - - present(controller, animated: false) - } - } - - func urlTapped(url: URL) { - let controller = SFSafariViewController(url: url) - controller.delegate = self - controller.dismissButtonStyle = .done - // controller.preferredBarTintColor = UIColor(named: "Secondary") - controller.preferredControlTintColor = UIColor(named: "Text") - - present(controller, animated: true) - } -} - -extension AccountTableViewController: SFSafariViewControllerDelegate { - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - controller.dismiss(animated: true) - } -} diff --git a/elpha-ios/AuthenticateViewController.swift b/elpha-ios/AuthenticateViewController.swift index b522a45..230d707 100644 --- a/elpha-ios/AuthenticateViewController.swift +++ b/elpha-ios/AuthenticateViewController.swift @@ -54,8 +54,7 @@ class AuthenticateViewController: UIViewController { let controller = SFSafariViewController(url: authorizeURL!) controller.delegate = self controller.dismissButtonStyle = .cancel - controller.preferredBarTintColor = UIColor(named: "Secondary") - controller.preferredControlTintColor = UIColor(named: "Text") + controller.preferredControlTintColor = UIColor(named: "Primary") present(controller, animated: true) } diff --git a/elpha-ios/Base.lproj/Main.storyboard b/elpha-ios/Base.lproj/Main.storyboard index 5819bc2..832b575 100644 --- a/elpha-ios/Base.lproj/Main.storyboard +++ b/elpha-ios/Base.lproj/Main.storyboard @@ -1237,10 +1237,10 @@ - + - + @@ -1256,11 +1256,11 @@ - + - + diff --git a/elpha-ios/CellHeightManager.swift b/elpha-ios/CellHeightManager.swift new file mode 100644 index 0000000..345d0df --- /dev/null +++ b/elpha-ios/CellHeightManager.swift @@ -0,0 +1,39 @@ +// +// CellHeightManager.swift +// elpha-ios +// +// Created by Dwayne Harris on 11/10/18. +// Copyright © 2018 Elpha. All rights reserved. +// + +import UIKit + +class CellHeightManager { + static private var cellHeightsDictionary: NSMutableDictionary = [:] + + static func set(statusID: String, height: CGFloat) { + cellHeightsDictionary[statusID] = height + } + + static func set(status: StatusMO?, height: CGFloat) { + if let id = status?.id { + set(statusID: id, height: height) + } + } + + static func get(statusID: String) -> CGFloat { + if let height = cellHeightsDictionary[statusID] as? CGFloat { + return height + } + + return UITableView.automaticDimension + } + + static func get(status: StatusMO?) -> CGFloat { + if let id = status?.id { + return get(statusID: id) + } + + return UITableView.automaticDimension + } +} diff --git a/elpha-ios/StatusTableViewController.swift b/elpha-ios/StatusTableViewController.swift index eba6aba..b9d0977 100644 --- a/elpha-ios/StatusTableViewController.swift +++ b/elpha-ios/StatusTableViewController.swift @@ -15,12 +15,12 @@ enum StatusType { case ancestor, status, descendant } -class StatusTableViewController: UITableViewController, UIGestureRecognizerDelegate { +class StatusTableViewController: AbstractStatusTableViewController, UIGestureRecognizerDelegate { public var status: StatusMO? = nil + var ancestors: [StatusMO] = [] var descendants: [StatusMO] = [] var feedbackGenerator: UINotificationFeedbackGenerator? = nil - var loading: Bool = false override func viewDidLoad() { super.viewDidLoad() @@ -209,6 +209,20 @@ extension StatusTableViewController { return 3 } + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if let cell = cell as? StatusTableViewCell { + CellHeightManager.set(status: cell.statusView.status, height: cell.frame.size.height) + } + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + switch indexPath.section { + case 0: return CellHeightManager.get(status: self.ancestors[indexPath.row]) + case 2: return CellHeightManager.get(status: self.descendants[indexPath.row]) + default: return UITableView.automaticDimension + } + } + override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { let height = CGFloat(25) @@ -330,44 +344,7 @@ extension StatusTableViewController { } } -extension StatusTableViewController: StatusViewDelegate { - func accountTapped(account: AccountMO) { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - - if let controller = storyboard.instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController { - controller.account = account - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func statusTapped(status: StatusMO) { - let storyboard = UIStoryboard(name: "Main", bundle: nil) - - if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController { - controller.status = status - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func attachmentTapped(status: StatusMO, index: Int) { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AttachmentPageViewController") as? AttachmentPageViewController { - controller.status = status - controller.attachmentIndex = index - - present(controller, animated: false) - } - } - - func urlTapped(url: URL) { - let controller = SFSafariViewController(url: url) - controller.delegate = self - controller.dismissButtonStyle = .done - // controller.preferredBarTintColor = UIColor(named: "Secondary") - controller.preferredControlTintColor = UIColor(named: "Text") - - present(controller, animated: true) - } - +extension StatusTableViewController { func boostTapped() { loadStatuses() } @@ -385,12 +362,6 @@ extension StatusTableViewController: StatusViewDelegate { } } -extension StatusTableViewController: SFSafariViewControllerDelegate { - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - controller.dismiss(animated: true) - } -} - extension StatusTableViewController: AttachmentManagerDelegate { func attachmentTapped(index: Int) { self.attachmentTapped(status: status!, index: index) diff --git a/elpha-ios/StatusView.swift b/elpha-ios/StatusView.swift index 57da748..f94ce60 100644 --- a/elpha-ios/StatusView.swift +++ b/elpha-ios/StatusView.swift @@ -63,6 +63,7 @@ class StatusView: UIView { var delegate: StatusViewDelegate? = nil var spoilerView: UIVisualEffectView? = nil var attachmentManager: AttachmentManager = AttachmentManager() + var feedbackGenerator: UINotificationFeedbackGenerator? = nil @IBAction func boostViewTapped(_ sender: Any) { if let delegate = delegate, let status = status { @@ -121,6 +122,8 @@ class StatusView: UIView { @IBAction func boostTapped(_ sender: Any) { if let status = status { + feedbackGenerator!.prepare() + if status.reblogged { status.reblogged = false status.reblogsCount = status.reblogsCount - 1 @@ -128,10 +131,12 @@ class StatusView: UIView { MastodonAPI.unreblog(statusID: status.id!) { error in guard error == nil else { AlertManager.shared.show(message: error!.localizedDescription, category: .error) + self.feedbackGenerator!.notificationOccurred(.error) return } AlertManager.shared.show(message: "Unboosted", category: .boosted) + self.feedbackGenerator!.notificationOccurred(.success) } } else { status.reblogged = true @@ -140,10 +145,12 @@ class StatusView: UIView { MastodonAPI.reblog(statusID: status.id!) { error in guard error == nil else { AlertManager.shared.show(message: error!.localizedDescription, category: .error) + self.feedbackGenerator!.notificationOccurred(.error) return } AlertManager.shared.show(message: "Boosted!", category: .boosted) + self.feedbackGenerator!.notificationOccurred(.success) } } @@ -154,6 +161,8 @@ class StatusView: UIView { @IBAction func favoriteTapped(_ sender: Any) { if let status = status { + feedbackGenerator!.prepare() + if status.favorited { status.favorited = false status.favoritesCount = status.favoritesCount - 1 @@ -161,10 +170,12 @@ class StatusView: UIView { MastodonAPI.unfavorite(statusID: status.id!) { error in guard error == nil else { AlertManager.shared.show(message: error!.localizedDescription, category: .error) + self.feedbackGenerator!.notificationOccurred(.error) return } AlertManager.shared.show(message: "Unfavorited", category: .favorited) + self.feedbackGenerator!.notificationOccurred(.success) } } else { status.favorited = true @@ -173,10 +184,12 @@ class StatusView: UIView { MastodonAPI.favorite(statusID: status.id!) { error in guard error == nil else { AlertManager.shared.show(message: error!.localizedDescription, category: .error) + self.feedbackGenerator!.notificationOccurred(.error) return } AlertManager.shared.show(message: "Favorited!", category: .favorited) + self.feedbackGenerator!.notificationOccurred(.success) } } @@ -210,6 +223,7 @@ class StatusView: UIView { contentView.frame = self.bounds attachmentManager.delegate = self contentTextView.delegate = self + feedbackGenerator = UINotificationFeedbackGenerator() } public func update(withStatus status: StatusMO) { diff --git a/elpha-ios/TimelineTableViewController.swift b/elpha-ios/TimelineTableViewController.swift index 5c43eaa..7a353db 100644 --- a/elpha-ios/TimelineTableViewController.swift +++ b/elpha-ios/TimelineTableViewController.swift @@ -12,18 +12,17 @@ import CoreData import UIKit import SafariServices -class TimelineTableViewController: UITableViewController { - let fetchLimit = 20 +class TimelineTableViewController: AbstractStatusTableViewController { var feedbackGenerator: UINotificationFeedbackGenerator? = nil var fetchedResultsController: NSFetchedResultsController? = nil - var loading: Bool = false - var currentPaginationContext: String { - guard let timeline = AuthenticationManager.session?.timeline, let categoryString = timeline.category else { - return "" - } - - switch TimelineCategory(rawValue: categoryString)! { + override var currentPaginationContext: String { + get { + guard let timeline = AuthenticationManager.session?.timeline, let categoryString = timeline.category else { + return "" + } + + switch TimelineCategory(rawValue: categoryString)! { case .home: return "timeline:home" case .local: @@ -34,6 +33,11 @@ class TimelineTableViewController: UITableViewController { return "timeline:tag:\(timeline.subcategory!)" case .favorites: return "timeline:favorites" + } + } + + set { + } } @@ -88,6 +92,20 @@ class TimelineTableViewController: UITableViewController { } } + override func loadMoreTapped(status: StatusMO, direction: PaginationDirection) { + if let markers = status.markers { + markers.forEach { marker in + if marker.context == self.currentPaginationContext && marker.item.direction == direction { + fetchTimeline(withPagination: marker.item) { error in + if error != nil { + AlertManager.shared.show(message: error!.localizedDescription, category: .error) + } + } + } + } + } + } + @objc func openSettings() { } @@ -96,10 +114,6 @@ class TimelineTableViewController: UITableViewController { performSegue(withIdentifier: "TimelinesSegue", sender: self) } - @objc func compose() { - AlertManager.shared.show(message: "We'll get the compose screen working one day.") - } - override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if segue.identifier == "TimelinesSegue" { if let destination = segue.destination as? TimelinesViewController { @@ -108,6 +122,10 @@ class TimelineTableViewController: UITableViewController { } } + @objc func compose() { + AlertManager.shared.show(message: "We'll get the compose screen working one day.") + } + func createDefaultTimelines(account: AccountMO) { let homeTimeline = TimelineMO(context: CoreDataManager.shared.context) homeTimeline.name = "Home" @@ -337,6 +355,16 @@ extension TimelineTableViewController { return count } + override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) { + if let cell = cell as? TimelineTableViewCell { + CellHeightManager.set(status: cell.statusView.status, height: cell.frame.size.height) + } + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return CellHeightManager.get(status: fetchedResultsController?.object(at: indexPath)) + } + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { guard let cell = tableView.dequeueReusableCell(withIdentifier: "TimelineTableViewCell", for: indexPath) as? TimelineTableViewCell else { fatalError("Unable to find reusable cell") @@ -403,58 +431,3 @@ extension TimelineTableViewController: TimelinesViewControllerDelegate { tableView.reloadData() } } - -extension TimelineTableViewController: StatusViewDelegate { - func accountTapped(account: AccountMO) { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController { - controller.account = account - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func statusTapped(status: StatusMO) { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController { - controller.status = status - self.navigationController?.pushViewController(controller, animated: true) - } - } - - func loadMoreTapped(status: StatusMO, direction: PaginationDirection) { - if let markers = status.markers { - markers.forEach { marker in - if marker.context == self.currentPaginationContext && marker.item.direction == direction { - fetchTimeline(withPagination: marker.item) { error in - if error != nil { - AlertManager.shared.show(message: error!.localizedDescription, category: .error) - } - } - } - } - } - } - - func attachmentTapped(status: StatusMO, index: Int) { - if let controller = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "AttachmentPageViewController") as? AttachmentPageViewController { - controller.status = status - controller.attachmentIndex = index - - present(controller, animated: false) - } - } - - func urlTapped(url: URL) { - let controller = SFSafariViewController(url: url) - controller.delegate = self - controller.dismissButtonStyle = .done - // controller.preferredBarTintColor = UIColor(named: "Secondary") - controller.preferredControlTintColor = UIColor(named: "Text") - - present(controller, animated: true) - } -} - -extension TimelineTableViewController: SFSafariViewControllerDelegate { - func safariViewControllerDidFinish(_ controller: SFSafariViewController) { - controller.dismiss(animated: true) - } -} diff --git a/elpha-ios/UITextViewFixed.swift b/elpha-ios/UITextViewFixed.swift index 283a068..fc53532 100644 --- a/elpha-ios/UITextViewFixed.swift +++ b/elpha-ios/UITextViewFixed.swift @@ -12,7 +12,10 @@ import UIKit override func layoutSubviews() { super.layoutSubviews() - textContainerInset = UIEdgeInsets.zero + let inset = UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0) + + contentInset = inset + textContainerInset = inset textContainer.lineFragmentPadding = 0 } }