diff --git a/.gitmodules b/.gitmodules index da938f5..6d9947b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -4,3 +4,6 @@ [submodule "Frameworks/AlamofireImage"] path = Frameworks/AlamofireImage url = https://github.com/Alamofire/AlamofireImage.git +[submodule "Frameworks/AlamofireNetworkActivityIndicator"] + path = Frameworks/AlamofireNetworkActivityIndicator + url = https://github.com/Alamofire/AlamofireNetworkActivityIndicator.git diff --git a/Frameworks/AlamofireNetworkActivityIndicator b/Frameworks/AlamofireNetworkActivityIndicator new file mode 160000 index 0000000..3ace5a9 --- /dev/null +++ b/Frameworks/AlamofireNetworkActivityIndicator @@ -0,0 +1 @@ +Subproject commit 3ace5a928804b60cad6945a0ba50a633a3ebb4ca diff --git a/Frameworks/MastodonKit b/Frameworks/MastodonKit deleted file mode 160000 index 27b48c0..0000000 --- a/Frameworks/MastodonKit +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 27b48c037aace80440396c2d1ef79621fe694cd1 diff --git a/Frameworks/OAuthSwift b/Frameworks/OAuthSwift deleted file mode 160000 index f46548a..0000000 --- a/Frameworks/OAuthSwift +++ /dev/null @@ -1 +0,0 @@ -Subproject commit f46548a7d15e8d7e2c30c418373ac4bd29946efd diff --git a/elpha-ios.xcodeproj/project.pbxproj b/elpha-ios.xcodeproj/project.pbxproj index 5f624f9..0c4b654 100644 --- a/elpha-ios.xcodeproj/project.pbxproj +++ b/elpha-ios.xcodeproj/project.pbxproj @@ -13,6 +13,8 @@ 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, ); }; }; 151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 157405C3215890BC00EEAAEB /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; + 1522EC7F2193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1522EC7C2193EBA10082C3FA /* AlamofireNetworkActivityIndicator.framework */; }; + 1522EC802193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1522EC7C2193EBA10082C3FA /* AlamofireNetworkActivityIndicator.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 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 */; }; @@ -127,6 +129,27 @@ remoteGlobalIDString = F8111E3219A95C8B0040E7D1; remoteInfo = "Alamofire iOS"; }; + 1522EC7B2193EBA10082C3FA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CB928391C66E1A600CE5F08; + remoteInfo = AlamofireNetworkActivityIndicator; + }; + 1522EC7D2193EBA10082C3FA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */; + proxyType = 2; + remoteGlobalIDString = 4CB928431C66E1A700CE5F08; + remoteInfo = AlamofireNetworkActivityIndicatorTests; + }; + 1522EC812193EBCB0082C3FA /* PBXContainerItemProxy */ = { + isa = PBXContainerItemProxy; + containerPortal = 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */; + proxyType = 1; + remoteGlobalIDString = 4CB928381C66E1A600CE5F08; + remoteInfo = AlamofireNetworkActivityIndicator; + }; 157405C2215890BC00EEAAEB /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */; @@ -187,6 +210,7 @@ files = ( 151AD4D9216899AD00F07403 /* AlamofireImage.framework in Embed Frameworks */, 151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */, + 1522EC802193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Embed Frameworks */, ); name = "Embed Frameworks"; runOnlyForDeploymentPostprocessing = 0; @@ -199,6 +223,7 @@ 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 = ""; }; + 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AlamofireNetworkActivityIndicator.xcodeproj; path = Frameworks/AlamofireNetworkActivityIndicator/AlamofireNetworkActivityIndicator.xcodeproj; sourceTree = ""; }; 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 = ""; }; @@ -250,6 +275,7 @@ files = ( 15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */, 157405D1215890D700EEAAEB /* Alamofire.framework in Frameworks */, + 1522EC7F2193EBCB0082C3FA /* AlamofireNetworkActivityIndicator.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -327,6 +353,15 @@ name = Extensions; sourceTree = ""; }; + 1522EC762193EBA10082C3FA /* Products */ = { + isa = PBXGroup; + children = ( + 1522EC7C2193EBA10082C3FA /* AlamofireNetworkActivityIndicator.framework */, + 1522EC7E2193EBA10082C3FA /* AlamofireNetworkActivityIndicatorTests.xctest */, + ); + name = Products; + sourceTree = ""; + }; 156FF05621779C140074D9CA /* API */ = { isa = PBXGroup; children = ( @@ -363,6 +398,7 @@ 157405AF2151A5DA00EEAAEB /* README.md */, 157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */, 1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */, + 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */, 15960E59213145E100C38CE9 /* elpha-ios */, 15960E58213145E100C38CE9 /* Products */, 157405D0215890D700EEAAEB /* Frameworks */, @@ -443,6 +479,7 @@ dependencies = ( 151AD4DB216899AD00F07403 /* PBXTargetDependency */, 151AD4E821689A0F00F07403 /* PBXTargetDependency */, + 1522EC822193EBCB0082C3FA /* PBXTargetDependency */, ); name = "elpha-ios"; productName = "elpha-ios"; @@ -485,6 +522,10 @@ ProductGroup = 1517EA702159D72200DE80D6 /* Products */; ProjectRef = 1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */; }, + { + ProductGroup = 1522EC762193EBA10082C3FA /* Products */; + ProjectRef = 1522EC752193EBA10082C3FA /* AlamofireNetworkActivityIndicator.xcodeproj */; + }, ); projectRoot = ""; targets = ( @@ -550,6 +591,20 @@ remoteRef = 1517EA912159D72200DE80D6 /* PBXContainerItemProxy */; sourceTree = BUILT_PRODUCTS_DIR; }; + 1522EC7C2193EBA10082C3FA /* AlamofireNetworkActivityIndicator.framework */ = { + isa = PBXReferenceProxy; + fileType = wrapper.framework; + path = AlamofireNetworkActivityIndicator.framework; + remoteRef = 1522EC7B2193EBA10082C3FA /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; + 1522EC7E2193EBA10082C3FA /* AlamofireNetworkActivityIndicatorTests.xctest */ = { + isa = PBXReferenceProxy; + fileType = wrapper.cfbundle; + path = AlamofireNetworkActivityIndicatorTests.xctest; + remoteRef = 1522EC7D2193EBA10082C3FA /* PBXContainerItemProxy */; + sourceTree = BUILT_PRODUCTS_DIR; + }; 157405C3215890BC00EEAAEB /* Alamofire.framework */ = { isa = PBXReferenceProxy; fileType = wrapper.framework; @@ -675,6 +730,11 @@ name = "Alamofire iOS"; targetProxy = 151AD4E721689A0F00F07403 /* PBXContainerItemProxy */; }; + 1522EC822193EBCB0082C3FA /* PBXTargetDependency */ = { + isa = PBXTargetDependency; + name = AlamofireNetworkActivityIndicator; + targetProxy = 1522EC812193EBCB0082C3FA /* PBXContainerItemProxy */; + }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -817,10 +877,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R9PMLQGTGZ; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "elpha-ios/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", @@ -839,10 +899,10 @@ ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CODE_SIGN_IDENTITY = "iPhone Developer"; - CODE_SIGN_STYLE = Automatic; - DEVELOPMENT_TEAM = R9PMLQGTGZ; + CODE_SIGN_STYLE = Manual; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = "elpha-ios/Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 12.0; + IPHONEOS_DEPLOYMENT_TARGET = 12.1; LD_RUNPATH_SEARCH_PATHS = ( "$(inherited)", "@executable_path/Frameworks", diff --git a/elpha-ios/AccountTableViewController.swift b/elpha-ios/AccountTableViewController.swift index b63adcb..061d968 100644 --- a/elpha-ios/AccountTableViewController.swift +++ b/elpha-ios/AccountTableViewController.swift @@ -9,6 +9,7 @@ import AlamofireImage import CoreData import UIKit +import SafariServices class AccountTableViewController: UITableViewController { @IBOutlet var headerView: UIView! @@ -25,18 +26,7 @@ class AccountTableViewController: UITableViewController { let fetchLimit = 20 var fetchedResultsController: NSFetchedResultsController? = nil var account: AccountMO? = nil - - var loading: Bool = false { - didSet { - DispatchQueue.main.async { - if self.loading { - self.refreshControl?.beginRefreshing() - } else { - self.refreshControl?.endRefreshing() - } - } - } - } + var loading: Bool = false var currentPaginationContext: String { guard let account = self.account else { @@ -373,4 +363,20 @@ extension AccountTableViewController: StatusViewDelegate { 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/AlertManager.swift b/elpha-ios/AlertManager.swift index c2e8f6d..b8f8854 100644 --- a/elpha-ios/AlertManager.swift +++ b/elpha-ios/AlertManager.swift @@ -112,6 +112,8 @@ class AlertManager { } } + print("ALERT: \(message)") + alerts.append(Alert(category: category, message: message)) start() } diff --git a/elpha-ios/AppDelegate.swift b/elpha-ios/AppDelegate.swift index 50f58e5..635ce40 100644 --- a/elpha-ios/AppDelegate.swift +++ b/elpha-ios/AppDelegate.swift @@ -6,6 +6,7 @@ // Copyright © 2018 Elpha. All rights reserved. // +import AlamofireNetworkActivityIndicator import CoreData import UIKit @@ -14,6 +15,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { var window: UIWindow? func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { + NetworkActivityIndicatorManager.shared.isEnabled = true return true } diff --git a/elpha-ios/AuthenticateViewController.swift b/elpha-ios/AuthenticateViewController.swift index 92ac645..b522a45 100644 --- a/elpha-ios/AuthenticateViewController.swift +++ b/elpha-ios/AuthenticateViewController.swift @@ -24,6 +24,14 @@ class AuthenticateViewController: UIViewController { instanceTextField.attributedPlaceholder = NSAttributedString(string: "mastodon.social", attributes: [NSAttributedString.Key.foregroundColor: UIColor.init(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)]) } + override func viewDidAppear(_ animated: Bool) { + super.viewDidAppear(animated) + + if AuthenticationManager.session != nil { + self.dismiss(animated: true) + } + } + override open var shouldAutorotate: Bool { return false } diff --git a/elpha-ios/Base.lproj/Main.storyboard b/elpha-ios/Base.lproj/Main.storyboard index 11522f3..5819bc2 100644 --- a/elpha-ios/Base.lproj/Main.storyboard +++ b/elpha-ios/Base.lproj/Main.storyboard @@ -4,6 +4,7 @@ + @@ -536,7 +537,7 @@ - + @@ -562,7 +563,7 @@ - + @@ -588,7 +589,7 @@ - + @@ -611,7 +612,7 @@ - + @@ -1088,19 +1089,22 @@ - + + + + - - - - + + + + @@ -1138,7 +1142,7 @@ - + @@ -1400,6 +1404,9 @@ + + + diff --git a/elpha-ios/MainStatusTableViewCell.swift b/elpha-ios/MainStatusTableViewCell.swift index 35cf4e0..edd05e5 100644 --- a/elpha-ios/MainStatusTableViewCell.swift +++ b/elpha-ios/MainStatusTableViewCell.swift @@ -12,7 +12,6 @@ class MainStatusTableViewCell: UITableViewCell { @IBOutlet var avatarImageView: UIImageView! @IBOutlet var displayNameLabel: UILabel! @IBOutlet var usernameLabel: UILabel! - @IBOutlet var contentLabel: UILabel! @IBOutlet var repliesImageView: UIImageView! @IBOutlet var repliesLabel: UILabel! @IBOutlet var boostsImageView: UIImageView! @@ -23,4 +22,5 @@ class MainStatusTableViewCell: UITableViewCell { @IBOutlet var timestampDateLabel: UILabel! @IBOutlet var timestampTimeLabel: UILabel! @IBOutlet var attachmentsView: UIView! + @IBOutlet var contentTextView: UITextViewFixed! } diff --git a/elpha-ios/StatusTableViewController.swift b/elpha-ios/StatusTableViewController.swift index fd02f5e..eba6aba 100644 --- a/elpha-ios/StatusTableViewController.swift +++ b/elpha-ios/StatusTableViewController.swift @@ -9,6 +9,7 @@ import AlamofireImage import CoreData import UIKit +import SafariServices enum StatusType { case ancestor, status, descendant @@ -18,22 +19,14 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg public var status: StatusMO? = nil var ancestors: [StatusMO] = [] var descendants: [StatusMO] = [] - - var loading: Bool = false { - didSet { - DispatchQueue.main.async { - if self.loading { - self.refreshControl?.beginRefreshing() - } else { - self.refreshControl?.endRefreshing() - } - } - } - } + var feedbackGenerator: UINotificationFeedbackGenerator? = nil + var loading: Bool = false override func viewDidLoad() { super.viewDidLoad() - navigationItem.title = "Detail" + + feedbackGenerator = UINotificationFeedbackGenerator() + navigationItem.title = "Toot" } override func viewDidAppear(_ animated: Bool) { @@ -53,6 +46,8 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg @IBAction func boostTapped(_ sender: Any) { if let status = status { + feedbackGenerator!.prepare() + if status.reblogged { status.reblogged = false status.reblogsCount = status.reblogsCount - 1 @@ -60,10 +55,12 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg 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 @@ -72,10 +69,12 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg 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) } } @@ -85,6 +84,8 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg @IBAction func favoriteTapped(_ sender: Any) { if let status = status { + feedbackGenerator!.prepare() + if status.favorited { status.favorited = false status.favoritesCount = status.favoritesCount - 1 @@ -92,10 +93,12 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg 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 @@ -104,10 +107,12 @@ class StatusTableViewController: UITableViewController, UIGestureRecognizerDeleg 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) } } @@ -264,7 +269,7 @@ extension StatusTableViewController { } if let content = status.content { - cell.contentLabel.attributedText = content.htmlAttributed(size: 16) + cell.contentTextView.attributedText = content.htmlAttributed(size: 16) } cell.attachmentsView.backgroundColor = UIColor.white @@ -353,6 +358,16 @@ extension StatusTableViewController: StatusViewDelegate { } } + 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) + } + func boostTapped() { loadStatuses() } @@ -370,6 +385,12 @@ 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 111828c..57da748 100644 --- a/elpha-ios/StatusView.swift +++ b/elpha-ios/StatusView.swift @@ -14,6 +14,7 @@ protocol StatusViewDelegate { func statusTapped(status: StatusMO) func loadMoreTapped(status: StatusMO, direction: PaginationDirection) func attachmentTapped(status: StatusMO, index: Int) + func urlTapped(url: URL) func boostTapped() func favoriteTapped() func revealTapped() @@ -208,6 +209,7 @@ class StatusView: UIView { addSubview(contentView) contentView.frame = self.bounds attachmentManager.delegate = self + contentTextView.delegate = self } public func update(withStatus status: StatusMO) { @@ -215,10 +217,8 @@ class StatusView: UIView { boostView.isHidden = true replyView.isHidden = true - attachmentsView.backgroundColor = UIColor.white attachmentsView.isHidden = true - spoilerImageView.isHidden = true let avatarFilter = AspectScaledToFillSizeWithRoundedCornersFilter( @@ -350,3 +350,22 @@ extension StatusView: AttachmentManagerDelegate { } } } + +extension StatusView: UITextViewDelegate { + func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool { + if let mentions = status?.mentions { + for mention in mentions { + if URL == mention.url { + if let account = MastodonDataManager.account(id: mention.id) { + delegate?.accountTapped(account: account) + } + + return false + } + } + } + + delegate?.urlTapped(url: URL) + return false + } +} diff --git a/elpha-ios/StatusView.xib b/elpha-ios/StatusView.xib index b9d5ec8..ea369d5 100644 --- a/elpha-ios/StatusView.xib +++ b/elpha-ios/StatusView.xib @@ -4,6 +4,7 @@ + @@ -266,14 +267,14 @@ - + - + diff --git a/elpha-ios/TimelineTableViewController.swift b/elpha-ios/TimelineTableViewController.swift index 8057bf4..5c43eaa 100644 --- a/elpha-ios/TimelineTableViewController.swift +++ b/elpha-ios/TimelineTableViewController.swift @@ -6,25 +6,17 @@ // Copyright © 2018 Elpha. All rights reserved. // +import Alamofire import AlamofireImage import CoreData import UIKit +import SafariServices class TimelineTableViewController: UITableViewController { - var fetchedResultsController: NSFetchedResultsController? = nil let fetchLimit = 20 - - var loading: Bool = false { - didSet { - DispatchQueue.main.async { - if self.loading { - self.refreshControl?.beginRefreshing() - } else { - self.refreshControl?.endRefreshing() - } - } - } - } + 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 { @@ -47,6 +39,8 @@ class TimelineTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() + + feedbackGenerator = UINotificationFeedbackGenerator() initializeFetchedResultsController() let moreButtonItem = UIBarButtonItem(image: UIImage(named: "More"), style: .plain, target: self, action: #selector(more)) @@ -55,6 +49,22 @@ class TimelineTableViewController: UITableViewController { navigationItem.leftBarButtonItems = [moreButtonItem] navigationItem.rightBarButtonItems = [composeButtonItem] + if let account = AuthenticationManager.session?.account { + Alamofire.request(account.avatarURL!).responseImage { response in + if let image = response.result.value { + let avatarButtonItem = UIBarButtonItem( + image: image.af_imageAspectScaled(toFit: CGSize(width: 30, height: 30)).af_imageRounded(withCornerRadius: 10).withRenderingMode(.alwaysOriginal), + style: .plain, + target: self, + action: #selector(self.openSettings) + ) + + avatarButtonItem.tintColor = UIColor.clear + self.navigationItem.leftBarButtonItems?.insert(avatarButtonItem, at: 0) + } + } + } + if let timeline = AuthenticationManager.session?.timeline { navigationItem.title = timeline.name } else { @@ -67,6 +77,10 @@ class TimelineTableViewController: UITableViewController { override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(animated) + if fetchedResultsController?.fetchedObjects?.count ?? 0 == 0 { + initializeFetchedResultsController() + } + fetchTimeline { error in if error != nil { AlertManager.shared.show(message: error!.localizedDescription, category: .error) @@ -74,6 +88,10 @@ class TimelineTableViewController: UITableViewController { } } + @objc func openSettings() { + + } + @objc func more() { performSegue(withIdentifier: "TimelinesSegue", sender: self) } @@ -162,6 +180,7 @@ class TimelineTableViewController: UITableViewController { DispatchQueue.main.async { var newStatusCount = 0 + self.feedbackGenerator!.prepare() for (index, status) in data.enumerated() { if let upsertResult = MastodonDataManager.upsertStatus(status) { @@ -201,6 +220,7 @@ class TimelineTableViewController: UITableViewController { if newStatusCount > 0 { let pluralization = newStatusCount == 1 ? "" : "s" AlertManager.shared.show(message: "\(newStatusCount) new toot\(pluralization)", category: .newStatuses) + self.feedbackGenerator!.notificationOccurred(.success) } CoreDataManager.shared.saveContext() @@ -421,4 +441,20 @@ extension TimelineTableViewController: StatusViewDelegate { 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) + } }