diff --git a/elpha-ios.xcodeproj/project.pbxproj b/elpha-ios.xcodeproj/project.pbxproj index 512988f..0d47920 100644 --- a/elpha-ios.xcodeproj/project.pbxproj +++ b/elpha-ios.xcodeproj/project.pbxproj @@ -7,13 +7,15 @@ objects = { /* Begin PBXBuildFile section */ - 151AD4D8216899AD00F07403 /* AlamofireImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1517EA842159D72200DE80D6 /* AlamofireImage.framework */; }; + 15131ED8216D8C680092B252 /* StatusView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15131ED7216D8C680092B252 /* StatusView.xib */; }; + 15131EF2216D8D570092B252 /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15131EF1216D8D570092B252 /* StatusView.swift */; }; + 15131EF4216DB8B90092B252 /* AccountTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15131EF3216DB8B90092B252 /* AccountTableViewController.swift */; }; + 15131EF6216DBA820092B252 /* AccountNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15131EF5216DBA820092B252 /* AccountNavigationController.swift */; }; 151AD4D9216899AD00F07403 /* AlamofireImage.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1517EA842159D72200DE80D6 /* AlamofireImage.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 151AD4DD216899E000F07403 /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B13215B438C007A326E /* OAuthSwift.framework */; }; 151AD4DE216899E000F07403 /* OAuthSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B13215B438C007A326E /* OAuthSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 151AD4E1216899F900F07403 /* MastodonKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B02215B3CC5007A326E /* MastodonKit.framework */; }; 151AD4E2216899F900F07403 /* MastodonKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B02215B3CC5007A326E /* MastodonKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; - 151AD4E521689A0F00F07403 /* Alamofire.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 157405C3215890BC00EEAAEB /* Alamofire.framework */; }; 151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 157405C3215890BC00EEAAEB /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405A72150588A00EEAAEB /* InstanceViewController.swift */; }; 157405B12151A5DA00EEAAEB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 157405AF2151A5DA00EEAAEB /* README.md */; }; @@ -37,8 +39,6 @@ 15960E7E21329FED00C38CE9 /* AuthenticateViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15960E7D21329FED00C38CE9 /* AuthenticateViewController.swift */; }; 15960E822136668500C38CE9 /* TimelinesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15960E812136668500C38CE9 /* TimelinesNavigationController.swift */; }; 15960E84213774FC00C38CE9 /* InstancesTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15960E83213774FC00C38CE9 /* InstancesTableViewController.swift */; }; - 15A79B07215B3CD5007A326E /* MastodonKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B02215B3CC5007A326E /* MastodonKit.framework */; }; - 15A79B20215B439A007A326E /* OAuthSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 15A79B13215B438C007A326E /* OAuthSwift.framework */; }; 15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1517EA842159D72200DE80D6 /* AlamofireImage.framework */; }; 15A79B43215EB959007A326E /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A79B42215EB959007A326E /* CoreDataManager.swift */; }; 15C91A02216AB2D600D97DC3 /* NewStatusesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15C91A01216AB2D600D97DC3 /* NewStatusesView.xib */; }; @@ -278,6 +278,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 15131ED7216D8C680092B252 /* StatusView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatusView.xib; sourceTree = ""; }; + 15131EF1216D8D570092B252 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = ""; }; + 15131EF3216DB8B90092B252 /* AccountTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewController.swift; sourceTree = ""; }; + 15131EF5216DBA820092B252 /* AccountNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountNavigationController.swift; sourceTree = ""; }; 1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AlamofireImage.xcodeproj; path = Frameworks/AlamofireImage/AlamofireImage.xcodeproj; sourceTree = ""; }; 157405A72150588A00EEAAEB /* InstanceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceViewController.swift; sourceTree = ""; }; 157405AF2151A5DA00EEAAEB /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; }; @@ -318,13 +322,9 @@ buildActionMask = 2147483647; files = ( 15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */, - 151AD4D8216899AD00F07403 /* AlamofireImage.framework in Frameworks */, 151AD4DD216899E000F07403 /* OAuthSwift.framework in Frameworks */, 151AD4E1216899F900F07403 /* MastodonKit.framework in Frameworks */, - 15A79B20215B439A007A326E /* OAuthSwift.framework in Frameworks */, - 15A79B07215B3CD5007A326E /* MastodonKit.framework in Frameworks */, 157405D1215890D700EEAAEB /* Alamofire.framework in Frameworks */, - 151AD4E521689A0F00F07403 /* Alamofire.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -372,6 +372,8 @@ children = ( 15C91A01216AB2D600D97DC3 /* NewStatusesView.xib */, 15C91A03216AB32500D97DC3 /* NewStatusesView.swift */, + 15131ED7216D8C680092B252 /* StatusView.xib */, + 15131EF1216D8D570092B252 /* StatusView.swift */, ); name = "Reusable Views"; sourceTree = ""; @@ -467,6 +469,8 @@ 15960E782132383600C38CE9 /* View Controllers */ = { isa = PBXGroup; children = ( + 15131EF5216DBA820092B252 /* AccountNavigationController.swift */, + 15131EF3216DB8B90092B252 /* AccountTableViewController.swift */, 15960E7D21329FED00C38CE9 /* AuthenticateViewController.swift */, 15960E83213774FC00C38CE9 /* InstancesTableViewController.swift */, 157405A72150588A00EEAAEB /* InstanceViewController.swift */, @@ -535,7 +539,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0940; - LastUpgradeCheck = 0940; + LastUpgradeCheck = 1000; ORGANIZATIONNAME = Elpha; TargetAttributes = { 15960E56213145E100C38CE9 = { @@ -775,6 +779,7 @@ 15960E64213145E200C38CE9 /* Assets.xcassets in Resources */, 157405B12151A5DA00EEAAEB /* README.md in Resources */, 15960E62213145E100C38CE9 /* Main.storyboard in Resources */, + 15131ED8216D8C680092B252 /* StatusView.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -790,14 +795,17 @@ 15960E7021321FA500C38CE9 /* Elpha.xcdatamodeld in Sources */, 15F9981721629965009E58DA /* TimelineTableViewController.swift in Sources */, 157405B42151A93E00EEAAEB /* InstancesDataManager.swift in Sources */, + 15131EF4216DB8B90092B252 /* AccountTableViewController.swift in Sources */, 15960E5F213145E100C38CE9 /* SecondViewController.swift in Sources */, 15F998352162C0E8009E58DA /* MastodonDataManager.swift in Sources */, 15960E7A2132387A00C38CE9 /* MainTabBarController.swift in Sources */, 15960E7C213272CD00C38CE9 /* AuthenticationManager.swift in Sources */, 15960E7E21329FED00C38CE9 /* AuthenticateViewController.swift in Sources */, 15960E5B213145E100C38CE9 /* AppDelegate.swift in Sources */, + 15131EF2216D8D570092B252 /* StatusView.swift in Sources */, 15960E7721322C6F00C38CE9 /* Configuration.swift in Sources */, 15C91A04216AB32500D97DC3 /* NewStatusesView.swift in Sources */, + 15131EF6216DBA820092B252 /* AccountNavigationController.swift in Sources */, 15960E7521322BF800C38CE9 /* KeychainWrapper.swift in Sources */, 157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */, 15960E7321322BC700C38CE9 /* KeychainItemAccessibility.swift in Sources */, diff --git a/elpha-ios/AccountNavigationController.swift b/elpha-ios/AccountNavigationController.swift new file mode 100644 index 0000000..c93aebc --- /dev/null +++ b/elpha-ios/AccountNavigationController.swift @@ -0,0 +1,13 @@ +// +// AccountNavigationController.swift +// elpha-ios +// +// Created by Dwayne Harris on 10/9/18. +// Copyright © 2018 Elpha. All rights reserved. +// + +import UIKit + +class AccountNavigationController: UINavigationController { + +} diff --git a/elpha-ios/AccountTableViewController.swift b/elpha-ios/AccountTableViewController.swift new file mode 100644 index 0000000..3d1bc91 --- /dev/null +++ b/elpha-ios/AccountTableViewController.swift @@ -0,0 +1,105 @@ +// +// AccountTableView.swift +// elpha-ios +// +// Created by Dwayne Harris on 10/9/18. +// Copyright © 2018 Elpha. All rights reserved. +// + +import AlamofireImage +import MastodonKit +import UIKit + +class AccountTableViewController: UITableViewController { + @IBOutlet var headerImageView: UIImageView! + @IBOutlet var avatarImageView: UIImageView! + @IBOutlet var displayNameLabel: UILabel! + @IBOutlet var usernameLabel: UILabel! + @IBOutlet var contentLabel: UILabel! + @IBOutlet var statusesLabel: UILabel! + @IBOutlet var followingLabel: UILabel! + @IBOutlet var followersLabel: UILabel! + + public var account: AccountMO? = nil + + private func setAccount(_ account: AccountMO) { + let avatarFilter = AspectScaledToFillSizeWithRoundedCornersFilter( + size: CGSize(width: 70.0, height: 70.0), + radius: 20.0, + divideRadiusByImageScale: true + ) + + if let headerURL = account.headerURL { + headerImageView.af_setImage(withURL: headerURL) + } + + if let avatarURL = account.avatarURL { + avatarImageView.af_setImage(withURL: avatarURL, filter: avatarFilter) + } + + displayNameLabel.text = account.displayName + usernameLabel.text = account.acct + + if let note = account.note { + do { + let styledContent = " \(note)" + let attributedText = try NSAttributedString( + data: styledContent.data(using: String.Encoding.unicode, allowLossyConversion: true)!, + options: [.documentType: NSAttributedString.DocumentType.html], + documentAttributes: nil + ) + + contentLabel.attributedText = attributedText + } catch { + print("\(error)") + } + } + + statusesLabel.text = NumberFormatter.localizedString(from: NSNumber(value: account.statusesCount), number: .decimal) + followingLabel.text = NumberFormatter.localizedString(from: NSNumber(value: account.followingCount), number: .decimal) + followersLabel.text = NumberFormatter.localizedString(from: NSNumber(value: account.followersCount), number: .decimal) + } + + override func viewDidLoad() { + super.viewDidLoad() + + if let navigationController = navigationController { + navigationController.view.backgroundColor = .clear + } + + if self.account == nil { + if let session = AuthenticationManager.shared.selectedSession { + self.account = session.account + } + } + + if let account = account { + setAccount(account) + } + } + + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if let account = self.account { + if let client = AuthenticationManager.shared.mkClientForSelectedSession() { + let request = Accounts.account(id: account.id!) + + client.run(request) { result in + switch result { + case .success(let remoteAccount, _): + self.account = MastodonDataManager.upsertAccount(remoteAccount) + + if let account = self.account { + DispatchQueue.main.async { + self.setAccount(account) + } + } + case .failure(let error): + print("\(error)") + } + } + } + } + } +} diff --git a/elpha-ios/Assets.xcassets/Account.imageset/Contents.json b/elpha-ios/Assets.xcassets/Account.imageset/Contents.json new file mode 100644 index 0000000..d44748b --- /dev/null +++ b/elpha-ios/Assets.xcassets/Account.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "user-circle.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/elpha-ios/Assets.xcassets/Account.imageset/user-circle.pdf b/elpha-ios/Assets.xcassets/Account.imageset/user-circle.pdf new file mode 100644 index 0000000..b40b54c Binary files /dev/null and b/elpha-ios/Assets.xcassets/Account.imageset/user-circle.pdf differ diff --git a/elpha-ios/Assets.xcassets/Comments.imageset/Contents.json b/elpha-ios/Assets.xcassets/Comments.imageset/Contents.json new file mode 100644 index 0000000..b5855c7 --- /dev/null +++ b/elpha-ios/Assets.xcassets/Comments.imageset/Contents.json @@ -0,0 +1,12 @@ +{ + "images" : [ + { + "idiom" : "universal", + "filename" : "comments.pdf" + } + ], + "info" : { + "version" : 1, + "author" : "xcode" + } +} \ No newline at end of file diff --git a/elpha-ios/Assets.xcassets/Comments.imageset/comments.pdf b/elpha-ios/Assets.xcassets/Comments.imageset/comments.pdf new file mode 100644 index 0000000..cd4bae0 Binary files /dev/null and b/elpha-ios/Assets.xcassets/Comments.imageset/comments.pdf differ diff --git a/elpha-ios/Base.lproj/Main.storyboard b/elpha-ios/Base.lproj/Main.storyboard index 8a0b97e..547f00a 100644 --- a/elpha-ios/Base.lproj/Main.storyboard +++ b/elpha-ios/Base.lproj/Main.storyboard @@ -113,7 +113,7 @@ - + @@ -472,42 +472,189 @@ - - + + - - + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - + @@ -522,7 +669,7 @@ - + @@ -530,34 +677,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -594,454 +713,27 @@ - - + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + - - - - + + + + - - - - - - - - - - - - - - - - - - - - - - - - - + @@ -1087,18 +779,32 @@ + + + + + + + + + + + + + + + + + + + + - - - + - - - - diff --git a/elpha-ios/NewStatusesView.swift b/elpha-ios/NewStatusesView.swift index 5a0a0ab..0391cf7 100644 --- a/elpha-ios/NewStatusesView.swift +++ b/elpha-ios/NewStatusesView.swift @@ -14,15 +14,15 @@ import UIKit override init(frame: CGRect) { super.init(frame: frame) - commonInit() + setup() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) - commonInit() + setup() } - private func commonInit() { + private func setup() { Bundle.main.loadNibNamed("NewStatusesView", owner: self, options: nil) addSubview(contentView) contentView.frame = self.bounds @@ -30,6 +30,11 @@ import UIKit } public func setCount(_ count: Int) { - mainLabel.text = "\(count) New Toots" + switch count { + case 1: + mainLabel.text = "1 New Toot" + default: + mainLabel.text = "\(count) New Toots" + } } } diff --git a/elpha-ios/NewStatusesView.xib b/elpha-ios/NewStatusesView.xib index 56c144b..decd370 100644 --- a/elpha-ios/NewStatusesView.xib +++ b/elpha-ios/NewStatusesView.xib @@ -21,16 +21,25 @@ + + + + + + + - + + + @@ -39,4 +48,7 @@ + + + diff --git a/elpha-ios/StatusView.swift b/elpha-ios/StatusView.swift new file mode 100644 index 0000000..102ca44 --- /dev/null +++ b/elpha-ios/StatusView.swift @@ -0,0 +1,55 @@ +// +// StatusStackView.swift +// elpha-ios +// +// Created by Dwayne Harris on 10/9/18. +// Copyright © 2018 Elpha. All rights reserved. +// + +import UIKit + +class StatusView: UIView { + @IBOutlet var contentView: UIView! + @IBOutlet var boostView: UIView! + @IBOutlet var boostAvatarImageView: UIImageView! + @IBOutlet var boostDisplayNameLabel: UILabel! + @IBOutlet var boostUsernameLabel: UILabel! + @IBOutlet var replyView: UIView! + @IBOutlet var replyAvatarImageView: UIImageView! + @IBOutlet var replyDisplayNameLabel: UILabel! + @IBOutlet var replyUsernameLabel: UILabel! + @IBOutlet var avatarImageView: UIImageView! + @IBOutlet var displayNameLabel: UILabel! + @IBOutlet var usernameLabel: UILabel! + @IBOutlet var contentLabel: UILabel! + @IBOutlet var timestampLabel: UILabel! + @IBOutlet var repliesImageView: UIImageView! + @IBOutlet var repliesLabel: UILabel! + @IBOutlet var boostsImageView: UIImageView! + @IBOutlet var boostsLabel: UILabel! + @IBOutlet var favoritesImageView: UIImageView! + @IBOutlet var favoritesLabel: UILabel! + @IBOutlet var topDividerView: UIView! + @IBOutlet var topLoadMoreView: UIView! + @IBOutlet var bottomDividerView: UIView! + @IBOutlet var bottomLoadMoreView: UIView! + @IBOutlet var attachmentsView: UIView! + @IBOutlet var attachmentsHeightConstraint: NSLayoutConstraint! + + override init(frame: CGRect) { + super.init(frame: frame) + setup() + } + + required init?(coder aDecoder: NSCoder) { + super.init(coder: aDecoder) + setup() + } + + private func setup() { + Bundle.main.loadNibNamed("StatusView", owner: self, options: nil) + addSubview(contentView) + contentView.frame = self.bounds + contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight] + } +} diff --git a/elpha-ios/StatusView.xib b/elpha-ios/StatusView.xib new file mode 100644 index 0000000..0fc6875 --- /dev/null +++ b/elpha-ios/StatusView.xib @@ -0,0 +1,473 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/elpha-ios/TimelineTableViewCell.swift b/elpha-ios/TimelineTableViewCell.swift index 95812ce..417e8f4 100644 --- a/elpha-ios/TimelineTableViewCell.swift +++ b/elpha-ios/TimelineTableViewCell.swift @@ -9,29 +9,5 @@ import UIKit class TimelineTableViewCell: UITableViewCell { - @IBOutlet var boostView: UIView! - @IBOutlet var boostAvatarImageView: UIImageView! - @IBOutlet var boostDisplayNameLabel: UILabel! - @IBOutlet var boostUsernameLabel: UILabel! - @IBOutlet var replyView: UIView! - @IBOutlet var replyAvatarImageView: UIImageView! - @IBOutlet var replyDisplayNameLabel: UILabel! - @IBOutlet var replyUsernameLabel: UILabel! - @IBOutlet var avatarImageView: UIImageView! - @IBOutlet var displayNameLabel: UILabel! - @IBOutlet var usernameLabel: UILabel! - @IBOutlet var contentLabel: UILabel! - @IBOutlet var timestampLabel: UILabel! - @IBOutlet var repliesImageView: UIImageView! - @IBOutlet var repliesLabel: UILabel! - @IBOutlet var boostsImageView: UIImageView! - @IBOutlet var boostsLabel: UILabel! - @IBOutlet var favoritesImageView: UIImageView! - @IBOutlet var favoritesLabel: UILabel! - @IBOutlet var topDividerView: UIView! - @IBOutlet var topLoadMoreView: UIView! - @IBOutlet var bottomDividerView: UIView! - @IBOutlet var bottomLoadMoreView: UIView! - @IBOutlet var attachmentsView: UIView! - @IBOutlet var attachmentsHeightConstraint: NSLayoutConstraint! + @IBOutlet var statusView: StatusView! } diff --git a/elpha-ios/TimelineTableViewController.swift b/elpha-ios/TimelineTableViewController.swift index ca119e0..d24f1c5 100644 --- a/elpha-ios/TimelineTableViewController.swift +++ b/elpha-ios/TimelineTableViewController.swift @@ -197,11 +197,19 @@ class TimelineTableViewController: UITableViewController { } let newStatuses = statuses.filter { $0.new } - DispatchQueue.main.async { - if let navigationController = self.navigationController as? TimelinesNavigationController, - let newStatusesView = navigationController.newStatusesView { - newStatusesView.isHidden = false - newStatusesView.setCount(newStatuses.count) + if newStatuses.count > -1 { + DispatchQueue.main.async { + if let navigationController = self.navigationController as? TimelinesNavigationController, + let newStatusesView = navigationController.newStatusesView { + newStatusesView.setCount(newStatuses.count) + newStatusesView.isHidden = false + self.view.layoutIfNeeded() + + UIView.animate(withDuration: 2.0, animations: { () -> Void in + navigationController.bottomLayoutConstraint?.constant = -20 + self.view.layoutIfNeeded() + }) + } } } @@ -286,16 +294,16 @@ extension TimelineTableViewController { fatalError("Unable to find reusable cell") } - cell.topDividerView.isHidden = false - cell.topLoadMoreView.isHidden = true - cell.boostView.isHidden = true - cell.replyView.isHidden = true - cell.bottomLoadMoreView.isHidden = true - cell.bottomDividerView.isHidden = false + cell.statusView.topDividerView.isHidden = false + cell.statusView.topLoadMoreView.isHidden = true + cell.statusView.boostView.isHidden = true + cell.statusView.replyView.isHidden = true + cell.statusView.bottomLoadMoreView.isHidden = true + cell.statusView.bottomDividerView.isHidden = false - cell.attachmentsView.backgroundColor = UIColor.white - cell.attachmentsHeightConstraint.constant = cell.frame.width - cell.attachmentsView.isHidden = true + cell.statusView.attachmentsView.backgroundColor = UIColor.white + cell.statusView.attachmentsHeightConstraint.constant = cell.frame.width + cell.statusView.attachmentsView.isHidden = true if let statuses = timelineStatuses() { let status = statuses[indexPath.row] @@ -313,14 +321,14 @@ extension TimelineTableViewController { let previousStatus = statuses[indexPath.row - 1] if let previousBoundary = boundaries.filtered(using: NSPredicate(format: "statusID = %@", previousStatus.id!)).first as? TimelineBoundaryMO { if !previousBoundary.start { - cell.topDividerView.isHidden = true - cell.topLoadMoreView.isHidden = false + cell.statusView.topDividerView.isHidden = true + cell.statusView.topLoadMoreView.isHidden = false } } } } } else { - cell.topDividerView.isHidden = true + cell.statusView.topDividerView.isHidden = true } if indexPath.row < statuses.count - 1 { @@ -329,8 +337,8 @@ extension TimelineTableViewController { let nextStatus = statuses[indexPath.row + 1] if let nextBoundary = boundaries.filtered(using: NSPredicate(format: "statusID = %@", nextStatus.id!)).first as? TimelineBoundaryMO { if nextBoundary.start { - cell.bottomDividerView.isHidden = true - cell.bottomLoadMoreView.isHidden = false + cell.statusView.bottomDividerView.isHidden = true + cell.statusView.bottomLoadMoreView.isHidden = false } } } @@ -339,14 +347,14 @@ extension TimelineTableViewController { func setStatusContent(_ status: StatusMO) { if let account = status.account { - cell.avatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) - cell.displayNameLabel.text = account.displayName - cell.usernameLabel.text = account.acct + cell.statusView.avatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) + cell.statusView.displayNameLabel.text = account.displayName + cell.statusView.usernameLabel.text = account.acct } if let attachments = status.attachments, attachments.count > 0 { - cell.attachmentsView.isHidden = false - AttachmentsManager.setupAttachmentsView(cell.attachmentsView, withAttachments: attachments) + cell.statusView.attachmentsView.isHidden = false + AttachmentsManager.setupAttachmentsView(cell.statusView.attachmentsView, withAttachments: attachments) } if let content = status.content { @@ -358,45 +366,45 @@ extension TimelineTableViewController { documentAttributes: nil ) - cell.contentLabel.attributedText = attributedText + cell.statusView.contentLabel.attributedText = attributedText } catch { print("\(error)") } } - cell.timestampLabel.text = status.createdAt!.timeAgo() - cell.repliesLabel.text = "0" - cell.boostsLabel.text = NumberFormatter.localizedString(from: NSNumber(value: status.reblogsCount), number: .decimal) - cell.favoritesLabel.text = NumberFormatter.localizedString(from: NSNumber(value: status.favouritesCount), number: .decimal) + cell.statusView.timestampLabel.text = status.createdAt!.timeAgo() + cell.statusView.repliesLabel.text = "0" + cell.statusView.boostsLabel.text = NumberFormatter.localizedString(from: NSNumber(value: status.reblogsCount), number: .decimal) + cell.statusView.favoritesLabel.text = NumberFormatter.localizedString(from: NSNumber(value: status.favouritesCount), number: .decimal) if status.reblogged { - cell.boostsImageView.image = UIImage(named: "Boost Bold") + cell.statusView.boostsImageView.image = UIImage(named: "Boost Bold") } else { - cell.boostsImageView.image = UIImage(named: "Boost Regular") + cell.statusView.boostsImageView.image = UIImage(named: "Boost Regular") } if status.favourited { - cell.favoritesImageView.image = UIImage(named: "Star Filled") + cell.statusView.favoritesImageView.image = UIImage(named: "Star Filled") } else { - cell.favoritesImageView.image = UIImage(named: "Star Regular") + cell.statusView.favoritesImageView.image = UIImage(named: "Star Regular") } } if let reblog = status.reblog { - cell.boostView.isHidden = false + cell.statusView.boostView.isHidden = false if let account = status.account { - cell.boostAvatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) - cell.boostDisplayNameLabel.text = account.displayName - cell.boostUsernameLabel.text = account.acct + cell.statusView.boostAvatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) + cell.statusView.boostDisplayNameLabel.text = account.displayName + cell.statusView.boostUsernameLabel.text = account.acct } setStatusContent(reblog) } else { if let account = status.account { - cell.avatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) - cell.displayNameLabel.text = account.displayName - cell.usernameLabel.text = account.acct + cell.statusView.avatarImageView.af_setImage(withURL: account.avatarURL!, filter: avatarFilter) + cell.statusView.displayNameLabel.text = account.displayName + cell.statusView.usernameLabel.text = account.acct } setStatusContent(status) @@ -404,10 +412,10 @@ extension TimelineTableViewController { if let replyAccountID = status.inReplyToAccountID { if let replyAccount = MastodonDataManager.getAccountByID(replyAccountID) { - cell.replyView.isHidden = false - cell.replyAvatarImageView.af_setImage(withURL: replyAccount.avatarURL!, filter: avatarFilter) - cell.replyDisplayNameLabel.text = replyAccount.displayName - cell.replyUsernameLabel.text = replyAccount.acct + cell.statusView.replyView.isHidden = false + cell.statusView.replyAvatarImageView.af_setImage(withURL: replyAccount.avatarURL!, filter: avatarFilter) + cell.statusView.replyDisplayNameLabel.text = replyAccount.displayName + cell.statusView.replyUsernameLabel.text = replyAccount.acct } } diff --git a/elpha-ios/TimelinesNavigationController.swift b/elpha-ios/TimelinesNavigationController.swift index 1e1f2b1..0bffa5c 100644 --- a/elpha-ios/TimelinesNavigationController.swift +++ b/elpha-ios/TimelinesNavigationController.swift @@ -10,6 +10,7 @@ import UIKit class TimelinesNavigationController: UINavigationController { public var newStatusesView: NewStatusesView? = nil + public var bottomLayoutConstraint: NSLayoutConstraint? = nil override func viewDidLoad() { super.viewDidLoad() @@ -32,11 +33,13 @@ class TimelinesNavigationController: UINavigationController { view.addSubview(blurEffectView) + bottomLayoutConstraint = blurEffectView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 50) + NSLayoutConstraint.activate([ blurEffectView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20), blurEffectView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20), - blurEffectView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20), blurEffectView.heightAnchor.constraint(equalToConstant: 50), + bottomLayoutConstraint!, ]) self.newStatusesView = newStatusesView