Browse Source

Development

master
Dwayne Harris 6 years ago
parent
commit
ae6b63ba01
  1. 161
      elpha-ios.xcodeproj/project.pbxproj
  2. 14
      elpha-ios/AccountTableViewController.swift
  3. 113
      elpha-ios/AlertManager.swift
  4. 23
      elpha-ios/AlertView.swift
  5. 16
      elpha-ios/AlertView.xib
  6. 3
      elpha-ios/AppDelegate.swift
  7. 21
      elpha-ios/AttachmentView.xib
  8. 7
      elpha-ios/AttachmentsManager.swift
  9. 96
      elpha-ios/AuthenticateViewController.swift
  10. 76
      elpha-ios/AuthenticationManager.swift
  11. 4
      elpha-ios/Base.lproj/Main.storyboard
  12. 1
      elpha-ios/Configuration.swift
  13. 2
      elpha-ios/MastodonAPI.swift
  14. 2
      elpha-ios/StatusTableViewController.swift
  15. 13
      elpha-ios/StatusView.swift
  16. 18
      elpha-ios/StatusView.xib
  17. 54
      elpha-ios/TimelineTableViewController.swift

161
elpha-ios.xcodeproj/project.pbxproj

@ -11,12 +11,10 @@
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 */; };
1517A6142182B87E00B33735 /* AttachmentView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 1517A6132182B87E00B33735 /* AttachmentView.xib */; };
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, ); }; };
151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 157405C3215890BC00EEAAEB /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
152734D22186DC74003DB3C8 /* TimelinesViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 152734D12186DC74003DB3C8 /* TimelinesViewController.swift */; };
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 */; };
156FF04F2175CDBC0074D9CA /* MainStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156FF04E2175CDBC0074D9CA /* MainStatusTableViewCell.swift */; };
@ -47,8 +45,8 @@
15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1517EA842159D72200DE80D6 /* AlamofireImage.framework */; };
15A79B43215EB959007A326E /* CoreDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15A79B42215EB959007A326E /* CoreDataManager.swift */; };
15BB72AB2171A8D4002F1FA4 /* TimelinesTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15BB72AA2171A8D4002F1FA4 /* TimelinesTableViewCell.swift */; };
15C91A02216AB2D600D97DC3 /* NewStatusesView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15C91A01216AB2D600D97DC3 /* NewStatusesView.xib */; };
15C91A04216AB32500D97DC3 /* NewStatusesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C91A03216AB32500D97DC3 /* NewStatusesView.swift */; };
15C91A02216AB2D600D97DC3 /* AlertView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 15C91A01216AB2D600D97DC3 /* AlertView.xib */; };
15C91A04216AB32500D97DC3 /* AlertView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15C91A03216AB32500D97DC3 /* AlertView.swift */; };
15F9981721629965009E58DA /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F9981621629965009E58DA /* TimelineTableViewController.swift */; };
15F998352162C0E8009E58DA /* MastodonDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 15F998342162C0E8009E58DA /* MastodonDataManager.swift */; };
/* End PBXBuildFile section */
@ -117,13 +115,6 @@
remoteGlobalIDString = 4C9043761AABBFC5001B4E60;
remoteInfo = "AlamofireImage iOS";
};
151AD4DF216899E000F07403 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 1;
remoteGlobalIDString = F43502791A6791B200038A29;
remoteInfo = OAuthSwift;
};
151AD4E721689A0F00F07403 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */;
@ -180,55 +171,6 @@
remoteGlobalIDString = E4202FE01B667AA100C997FB;
remoteInfo = "Alamofire watchOS";
};
15A79B12215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = F435027A1A6791B200038A29;
remoteInfo = OAuthSwift;
};
15A79B14215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C48B28021AFA598D00C7DEF6;
remoteInfo = OAuthSwiftOSX;
};
15A79B16215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C4B6EE1E1BF74CE300443596;
remoteInfo = OAuthSwiftTVOS;
};
15A79B18215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C40890C01C11B37000E3146A;
remoteInfo = OAuthSwiftWatchOS;
};
15A79B1A215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = F451E3C5195B8CD80051434C;
remoteInfo = OAuthSwiftDemo;
};
15A79B1C215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C49FD5241AFB5DF500791E1A;
remoteInfo = OAuthSwiftOSXDemo;
};
15A79B1E215B438C007A326E /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = C4D50DF71BFB693F0053B624;
remoteInfo = OAuthSwiftTests;
};
/* End PBXContainerItemProxy section */
/* Begin PBXCopyFilesBuildPhase section */
@ -238,7 +180,6 @@
dstPath = "";
dstSubfolderSpec = 10;
files = (
151AD4DE216899E000F07403 /* OAuthSwift.framework in Embed Frameworks */,
151AD4D9216899AD00F07403 /* AlamofireImage.framework in Embed Frameworks */,
151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */,
);
@ -252,9 +193,9 @@
15131EF1216D8D570092B252 /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
15131EF3216DB8B90092B252 /* AccountTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewController.swift; sourceTree = "<group>"; };
15131EF5216DBA820092B252 /* AccountNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountNavigationController.swift; sourceTree = "<group>"; };
1517A6132182B87E00B33735 /* AttachmentView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AttachmentView.xib; sourceTree = "<group>"; };
1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AlamofireImage.xcodeproj; path = Frameworks/AlamofireImage/AlamofireImage.xcodeproj; sourceTree = "<group>"; };
152734D12186DC74003DB3C8 /* TimelinesViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesViewController.swift; sourceTree = "<group>"; };
1539509021894A38009BA6E7 /* AlertManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertManager.swift; sourceTree = "<group>"; };
156FF014217289380074D9CA /* AccountTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountTableViewCell.swift; sourceTree = "<group>"; };
156FF0302174797E0074D9CA /* StatusTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewController.swift; sourceTree = "<group>"; };
156FF04E2175CDBC0074D9CA /* MainStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainStatusTableViewCell.swift; sourceTree = "<group>"; };
@ -284,11 +225,10 @@
15960E7D21329FED00C38CE9 /* AuthenticateViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AuthenticateViewController.swift; sourceTree = "<group>"; };
15960E812136668500C38CE9 /* TimelinesNavigationController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesNavigationController.swift; sourceTree = "<group>"; };
15960E83213774FC00C38CE9 /* InstancesTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesTableViewController.swift; sourceTree = "<group>"; };
15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = OAuthSwift.xcodeproj; path = Frameworks/OAuthSwift/OAuthSwift.xcodeproj; sourceTree = "<group>"; };
15A79B42215EB959007A326E /* CoreDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CoreDataManager.swift; sourceTree = "<group>"; };
15BB72AA2171A8D4002F1FA4 /* TimelinesTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesTableViewCell.swift; sourceTree = "<group>"; };
15C91A01216AB2D600D97DC3 /* NewStatusesView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = NewStatusesView.xib; sourceTree = "<group>"; };
15C91A03216AB32500D97DC3 /* NewStatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NewStatusesView.swift; sourceTree = "<group>"; };
15C91A01216AB2D600D97DC3 /* AlertView.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = AlertView.xib; sourceTree = "<group>"; };
15C91A03216AB32500D97DC3 /* AlertView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AlertView.swift; sourceTree = "<group>"; };
15F9981621629965009E58DA /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
15F998342162C0E8009E58DA /* MastodonDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonDataManager.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -299,7 +239,6 @@
buildActionMask = 2147483647;
files = (
15A79B2E215C63B6007A326E /* AlamofireImage.framework in Frameworks */,
151AD4DD216899E000F07403 /* OAuthSwift.framework in Frameworks */,
157405D1215890D700EEAAEB /* Alamofire.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -334,6 +273,7 @@
151AD4AC2166DD0200F07403 /* Managers */ = {
isa = PBXGroup;
children = (
1539509021894A38009BA6E7 /* AlertManager.swift */,
1574148C2169AD0100C841BD /* AttachmentsManager.swift */,
15960E7B213272CD00C38CE9 /* AuthenticationManager.swift */,
15A79B42215EB959007A326E /* CoreDataManager.swift */,
@ -346,9 +286,8 @@
151AD4AD2166DD1B00F07403 /* Reusable Views */ = {
isa = PBXGroup;
children = (
1517A6132182B87E00B33735 /* AttachmentView.xib */,
15C91A03216AB32500D97DC3 /* NewStatusesView.swift */,
15C91A01216AB2D600D97DC3 /* NewStatusesView.xib */,
15C91A03216AB32500D97DC3 /* AlertView.swift */,
15C91A01216AB2D600D97DC3 /* AlertView.xib */,
15131EF1216D8D570092B252 /* StatusView.swift */,
15131ED7216D8C680092B252 /* StatusView.xib */,
);
@ -412,7 +351,6 @@
157405AF2151A5DA00EEAAEB /* README.md */,
157405B7215890BC00EEAAEB /* Alamofire.xcodeproj */,
1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */,
15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */,
15960E59213145E100C38CE9 /* elpha-ios */,
15960E58213145E100C38CE9 /* Products */,
157405D0215890D700EEAAEB /* Frameworks */,
@ -467,26 +405,12 @@
15960E792132387A00C38CE9 /* MainTabBarController.swift */,
156FF0302174797E0074D9CA /* StatusTableViewController.swift */,
15960E812136668500C38CE9 /* TimelinesNavigationController.swift */,
15F9981621629965009E58DA /* TimelineTableViewController.swift */,
152734D12186DC74003DB3C8 /* TimelinesViewController.swift */,
15F9981621629965009E58DA /* TimelineTableViewController.swift */,
);
name = "View Controllers";
sourceTree = "<group>";
};
15A79B09215B438C007A326E /* Products */ = {
isa = PBXGroup;
children = (
15A79B13215B438C007A326E /* OAuthSwift.framework */,
15A79B15215B438C007A326E /* OAuthSwift.framework */,
15A79B17215B438C007A326E /* OAuthSwift.framework */,
15A79B19215B438C007A326E /* OAuthSwift.framework */,
15A79B1B215B438C007A326E /* OAuthSwiftDemo.app */,
15A79B1D215B438C007A326E /* OAuthSwiftOSXDemo.app */,
15A79B1F215B438C007A326E /* OAuthSwiftTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@ -503,7 +427,6 @@
);
dependencies = (
151AD4DB216899AD00F07403 /* PBXTargetDependency */,
151AD4E0216899E000F07403 /* PBXTargetDependency */,
151AD4E821689A0F00F07403 /* PBXTargetDependency */,
);
name = "elpha-ios";
@ -547,10 +470,6 @@
ProductGroup = 1517EA702159D72200DE80D6 /* Products */;
ProjectRef = 1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */;
},
{
ProductGroup = 15A79B09215B438C007A326E /* Products */;
ProjectRef = 15A79B08215B438C007A326E /* OAuthSwift.xcodeproj */;
},
);
projectRoot = "";
targets = (
@ -665,55 +584,6 @@
remoteRef = 157405CE215890BC00EEAAEB /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B13215B438C007A326E /* OAuthSwift.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = OAuthSwift.framework;
remoteRef = 15A79B12215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B15215B438C007A326E /* OAuthSwift.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = OAuthSwift.framework;
remoteRef = 15A79B14215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B17215B438C007A326E /* OAuthSwift.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = OAuthSwift.framework;
remoteRef = 15A79B16215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B19215B438C007A326E /* OAuthSwift.framework */ = {
isa = PBXReferenceProxy;
fileType = wrapper.framework;
path = OAuthSwift.framework;
remoteRef = 15A79B18215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B1B215B438C007A326E /* OAuthSwiftDemo.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = OAuthSwiftDemo.app;
remoteRef = 15A79B1A215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B1D215B438C007A326E /* OAuthSwiftOSXDemo.app */ = {
isa = PBXReferenceProxy;
fileType = wrapper.application;
path = OAuthSwiftOSXDemo.app;
remoteRef = 15A79B1C215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
15A79B1F215B438C007A326E /* OAuthSwiftTests.xctest */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = OAuthSwiftTests.xctest;
remoteRef = 15A79B1E215B438C007A326E /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
/* End PBXReferenceProxy section */
/* Begin PBXResourcesBuildPhase section */
@ -722,12 +592,11 @@
buildActionMask = 2147483647;
files = (
15960E67213145E200C38CE9 /* LaunchScreen.storyboard in Resources */,
15C91A02216AB2D600D97DC3 /* NewStatusesView.xib in Resources */,
15C91A02216AB2D600D97DC3 /* AlertView.xib in Resources */,
15960E64213145E200C38CE9 /* Assets.xcassets in Resources */,
157405B12151A5DA00EEAAEB /* README.md in Resources */,
15960E62213145E100C38CE9 /* Main.storyboard in Resources */,
15131ED8216D8C680092B252 /* StatusView.xib in Resources */,
1517A6142182B87E00B33735 /* AttachmentView.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -738,6 +607,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1539509121894A38009BA6E7 /* AlertManager.swift in Sources */,
159048AF214F5015004F4014 /* InstancesTableViewCell.swift in Sources */,
15960E84213774FC00C38CE9 /* InstancesTableViewController.swift in Sources */,
15960E7021321FA500C38CE9 /* Elpha.xcdatamodeld in Sources */,
@ -755,7 +625,7 @@
156FF07221779C650074D9CA /* InstanceRequest.swift in Sources */,
15960E7721322C6F00C38CE9 /* Configuration.swift in Sources */,
156FF07021779C570074D9CA /* MastodonAPI.swift in Sources */,
15C91A04216AB32500D97DC3 /* NewStatusesView.swift in Sources */,
15C91A04216AB32500D97DC3 /* AlertView.swift in Sources */,
15131EF6216DBA820092B252 /* AccountNavigationController.swift in Sources */,
15960E7521322BF800C38CE9 /* KeychainWrapper.swift in Sources */,
157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */,
@ -780,11 +650,6 @@
name = "AlamofireImage iOS";
targetProxy = 151AD4DA216899AD00F07403 /* PBXContainerItemProxy */;
};
151AD4E0216899E000F07403 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = OAuthSwift;
targetProxy = 151AD4DF216899E000F07403 /* PBXContainerItemProxy */;
};
151AD4E821689A0F00F07403 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
name = "Alamofire iOS";

14
elpha-ios/AccountTableViewController.swift

@ -359,10 +359,16 @@ extension AccountTableViewController: StatusViewDelegate {
}
}
func loadMoreTapped(pagination: PaginationItem) {
fetchStatuses(withPagination: pagination) { error in
if error != nil {
print("\(String(describing: error))")
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 {
print("\(String(describing: error))")
}
}
}
}
}
}

113
elpha-ios/AlertManager.swift

@ -0,0 +1,113 @@
//
// AlertManager.swift
// elpha-ios
//
// Created by Dwayne Harris on 10/30/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import UIKit
enum AlertCategory {
case normal, newStatuses, noConnection, error
}
class Alert {
let category: AlertCategory
let message: String
init(category: AlertCategory, message: String) {
self.category = category
self.message = message
}
}
class AlertManager {
static let shared = AlertManager()
static let alertStartPosition: CGFloat = 100.0
var done: Bool = true
var alertView: AlertView? = nil
var bottomLayoutConstraint: NSLayoutConstraint? = nil
var alerts: [Alert] = []
func createAlertView() {
guard alertView == nil else {
return
}
alertView = AlertView()
alertView!.translatesAutoresizingMaskIntoConstraints = false
let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffect.Style.prominent))
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
blurEffectView.contentView.addSubview(alertView!)
blurEffectView.layer.cornerRadius = 10
blurEffectView.layer.masksToBounds = true
NSLayoutConstraint.activate([
alertView!.leadingAnchor.constraint(equalTo: blurEffectView.leadingAnchor),
alertView!.trailingAnchor.constraint(equalTo: blurEffectView.trailingAnchor),
alertView!.topAnchor.constraint(equalTo: blurEffectView.topAnchor),
alertView!.bottomAnchor.constraint(equalTo: blurEffectView.bottomAnchor),
])
let view = UIApplication.shared.keyWindow!
view.addSubview(blurEffectView)
bottomLayoutConstraint = blurEffectView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: AlertManager.alertStartPosition)
NSLayoutConstraint.activate([
blurEffectView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
blurEffectView.widthAnchor.constraint(equalToConstant: 200),
blurEffectView.heightAnchor.constraint(equalToConstant: 50),
bottomLayoutConstraint!,
])
}
private func start() {
guard done else {
return
}
done = false
UIView.animate(withDuration: 1.0, animations: {
self.bottomLayoutConstraint?.constant = AlertManager.alertStartPosition
}) { _ in
self.alertView?.setAlert(self.alerts.first!)
UIView.animate(withDuration: 1.0, animations: {
self.bottomLayoutConstraint?.constant = 20
}) { _ in
_ = self.alerts.remove(at: 0)
DispatchQueue.main.asyncAfter(deadline: .now() + 5) {
UIView.animate(withDuration: 1.0, animations: {
self.bottomLayoutConstraint?.constant = AlertManager.alertStartPosition
}) { _ in
self.done = true
if self.alerts.count > 0 {
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.start()
}
}
}
}
}
}
}
func show(message: String, category: AlertCategory = .normal) {
if let alert = alerts.last {
if alert.category == category {
return
}
}
alerts.append(Alert(category: category, message: message))
start()
}
}

23
elpha-ios/NewStatusesView.swift → elpha-ios/AlertView.swift

@ -8,9 +8,12 @@
import UIKit
@IBDesignable class NewStatusesView: UIView {
@IBDesignable class AlertView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet var mainLabel: UILabel!
@IBOutlet var alertImageView: UIImageView!
@IBOutlet var alertLabel: UILabel!
var alert: Alert? = nil
override init(frame: CGRect) {
super.init(frame: frame)
@ -23,18 +26,20 @@ import UIKit
}
private func setup() {
Bundle.main.loadNibNamed("NewStatusesView", owner: self, options: nil)
Bundle.main.loadNibNamed("AlertView", owner: self, options: nil)
addSubview(contentView)
contentView.frame = self.bounds
contentView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
}
public func setCount(_ count: Int) {
switch count {
case 1:
mainLabel.text = "1 New Toot"
default:
mainLabel.text = "\(count) New Toots"
public func setAlert(_ alert: Alert) {
switch alert.category {
case .newStatuses:
alertImageView.image = UIImage(named: "Comments")
alertLabel.text = alert.message
default:
alertImageView.image = UIImage(named: "Alert")
alertLabel.text = alert.message
}
}
}

16
elpha-ios/NewStatusesView.xib → elpha-ios/AlertView.xib

@ -1,18 +1,19 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14460.20"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="NewStatusesView" customModule="elpha_ios" customModuleProvider="target">
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="AlertView" customModule="elpha_ios" customModuleProvider="target">
<connections>
<outlet property="alertImageView" destination="clq-3k-X29" id="hQ3-B2-ZSk"/>
<outlet property="alertLabel" destination="uLF-4h-Bxo" id="6uf-1f-pS2"/>
<outlet property="contentView" destination="iN0-l3-epB" id="COo-K8-7Wi"/>
<outlet property="mainLabel" destination="uLF-4h-Bxo" id="KHJ-Zg-Cre"/>
</connections>
</placeholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
@ -20,13 +21,13 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="180"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="New Toots" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uLF-4h-Bxo">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Message" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="uLF-4h-Bxo">
<rect key="frame" x="55" y="81.5" width="312" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" red="0.090196078430000007" green="0.047058823530000002" blue="0.28627450980000002" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Comments" translatesAutoresizingMaskIntoConstraints="NO" id="clq-3k-X29">
<imageView userInteractionEnabled="NO" contentMode="center" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="clq-3k-X29">
<rect key="frame" x="20" y="80" width="25" height="20"/>
<constraints>
<constraint firstAttribute="width" constant="25" id="GaN-Tw-djA"/>
@ -48,7 +49,4 @@
<point key="canvasLocation" x="-574" y="-232"/>
</view>
</objects>
<resources>
<image name="Comments" width="25" height="20"/>
</resources>
</document>

3
elpha-ios/AppDelegate.swift

@ -7,7 +7,6 @@
//
import CoreData
import OAuthSwift
import UIKit
@UIApplicationMain
@ -20,7 +19,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
if (url.host == "oauth") {
OAuthSwift.handle(url: url)
AuthenticationManager.handle(url: url)
}
return true

21
elpha-ios/AttachmentView.xib

@ -1,21 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="14313.18" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14283.14"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
<view contentMode="scaleToFill" id="iN0-l3-epB">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
</view>
</objects>
</document>

7
elpha-ios/AttachmentsManager.swift

@ -133,13 +133,6 @@ class AttachmentsManager {
view.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
/*
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: halfWidth),
imageView.heightAnchor.constraint(equalToConstant: halfWidth),
])
*/
}
NSLayoutConstraint.activate([

96
elpha-ios/AuthenticateViewController.swift

@ -8,90 +8,60 @@
import Alamofire
import CoreData
import OAuthSwift
import UIKit
import SafariServices
class AuthenticateViewController: UIViewController {
class AuthenticateViewController: UIViewController, SFSafariViewControllerDelegate, AuthenticationDelegate {
@IBOutlet var signInButton: UIButton!
@IBOutlet var instanceTextField: UITextField!
var oauthswift: OAuthSwift?
let defaultInstanceName = "mastodon.social"
override func viewDidLoad() {
super.viewDidLoad()
signInButton.layer.cornerRadius = 10
signInButton.clipsToBounds = true
randomInstanceName { instance in
self.instanceTextField.attributedPlaceholder = NSAttributedString(string: instance, attributes: [NSAttributedString.Key.foregroundColor: UIColor.init(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)])
}
instanceTextField.attributedPlaceholder = NSAttributedString(string: "mastodon.social", attributes: [NSAttributedString.Key.foregroundColor: UIColor.init(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)])
}
override open var shouldAutorotate: Bool {
return false
}
func randomInstanceName(completion: @escaping (String) -> Void) {
let requestURL = "\(Config.instancesServiceURL)\(Config.instancesServiceRandomEndpoint)?count=1"
let headers: HTTPHeaders = ["Authorization": "Bearer \(Config.instancesServiceSecret)"]
Alamofire.request(requestURL, headers: headers).validate().responseJSON { response in
switch response.result {
case .success(let value):
guard let result = value as? [String: Any],
let instances = result["instances"] as? [Any],
let instance = instances.first as? [String: Any],
let name = instance["name"] as? String else {
completion(self.defaultInstanceName)
return
}
completion(name)
case .failure(let error):
print("\(error)")
completion(self.defaultInstanceName)
}
}
func authenticationSuccess() {
self.dismiss(animated: true)
}
func authenticationFailure(error: Error?) {
AlertManager.shared.show(message: error?.localizedDescription ?? "Authentication error", category: .error)
}
func authorize(client: ClientMO) {
let oauthswift = OAuth2Swift(
consumerKey: client.clientID!,
consumerSecret: client.clientSecret!,
authorizeUrl: "https://\(client.host!)/oauth/authorize",
accessTokenUrl: "https://\(client.host!)/oauth/token",
responseType: "code"
)
AuthenticationManager.authenticationState = NSUUID().uuidString
AuthenticationManager.authenticationClient = client
AuthenticationManager.authenticationDelegate = self
oauthswift.authorizeURLHandler = OAuthSwiftOpenURLExternally.sharedInstance
self.oauthswift = oauthswift
let parameters = [
"client_id": client.clientID!,
"response_type": "code",
"redirect_uri": Config.clientRedirectURI,
"scope": "read write follow".addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)!,
]
let _ = oauthswift.authorize(
withCallbackURL: URL(string: "elpha://oauth")!,
scope: "read write follow",
state: NSUUID().uuidString,
success: { credential, _, _ in
let token = credential.oauthToken
let serverURL = URL(string: "https://\(client.host!)")
MastodonAPI.currentUser(token: token, serverURL: serverURL!) { data, error in
guard let data = data, error == nil else {
print("\(String(describing: error))")
return
}
let account = MastodonDataManager.upsertAccount(data)
_ = AuthenticationManager.saveSession(client: client, account: account!, token: credential.oauthToken)
self.dismiss(animated: true)
}
},
failure: { error in
print("\(error)")
}
)
let parameterString = parameters.map { "\($0.key)=\($0.value)" }.joined(separator: "&")
let authorizeURL = URL(string: "https://\(client.host!)/oauth/authorize?\(parameterString)")
let controller = SFSafariViewController(url: authorizeURL!)
controller.delegate = self
controller.dismissButtonStyle = .cancel
controller.preferredBarTintColor = UIColor(named: "Secondary")
controller.preferredControlTintColor = UIColor(named: "Text")
present(controller, animated: true)
}
func safariViewControllerDidFinish(_ controller: SFSafariViewController) {
controller.dismiss(animated: true)
}
@IBAction func signIn(_ sender: Any) {
@ -145,7 +115,7 @@ class AuthenticateViewController: UIViewController {
}
}
} catch {
print("\(error)")
AlertManager.shared.show(message: error.localizedDescription, category: .error)
}
}
}

76
elpha-ios/AuthenticationManager.swift

@ -6,10 +6,20 @@
// Copyright © 2018 Elpha. All rights reserved.
//
import Alamofire
import CoreData
import UIKit
protocol AuthenticationDelegate {
func authenticationSuccess()
func authenticationFailure(error: Error?)
}
class AuthenticationManager {
static var authenticationState: String? = nil
static var authenticationClient: ClientMO? = nil
static var authenticationDelegate: AuthenticationDelegate? = nil
static var sessions: [SessionMO] {
get {
do {
@ -64,4 +74,70 @@ class AuthenticationManager {
return session
}
static func handle(url: URL) {
guard let state = authenticationState, let client = authenticationClient else {
return
}
if let components = URLComponents(url: url, resolvingAgainstBaseURL: false), let queryItems = components.queryItems {
var code: String?
for item in queryItems {
switch item.name.lowercased() {
case "code":
code = item.value
case "state":
if item.value != state {
if let delegate = self.authenticationDelegate {
delegate.authenticationFailure(error: nil)
}
return
}
default:
continue
}
}
let parameters: Parameters = [
"client_id": client.clientID!,
"client_secret": client.clientSecret!,
"grant_type": "authorization_code",
"code": code!,
"redirect_uri": Config.clientRedirectURI,
]
Alamofire.request(
"https://\(client.host!)/oauth/token",
method: .post,
parameters: parameters,
encoding: URLEncoding.default
).validate().responseJSON { response in
switch response.result {
case .success(let data):
let serverURL = URL(string: "https://\(client.host!)")
if let json = data as? [String: Any], let token = json["access_token"] as? String {
MastodonAPI.currentUser(token: token, serverURL: serverURL!) { data, error in
guard let data = data, error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
return
}
let account = MastodonDataManager.upsertAccount(data)
_ = AuthenticationManager.saveSession(client: client, account: account!, token: token)
if let delegate = self.authenticationDelegate {
delegate.authenticationSuccess()
}
}
}
case .failure(let error):
if let delegate = self.authenticationDelegate {
delegate.authenticationFailure(error: error)
}
}
}
}
}
}

4
elpha-ios/Base.lproj/Main.storyboard

@ -786,7 +786,6 @@
<nil key="highlightedColor"/>
</label>
</subviews>
<color key="backgroundColor" name="Background Secondary"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="bXM-kl-c1F" secondAttribute="trailing" constant="15" id="2Bp-NG-HmK"/>
<constraint firstItem="bXM-kl-c1F" firstAttribute="centerY" secondItem="l7S-vH-H0D" secondAttribute="centerY" constant="5" id="Lua-42-P7W"/>
@ -1266,9 +1265,6 @@
<image name="Message" width="20" height="20"/>
<image name="Star Regular" width="22" height="22"/>
<image name="Timelines" width="25" height="25"/>
<namedColor name="Background Secondary">
<color red="0.93725490196078431" green="0.93725490196078431" blue="0.93725490196078431" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Primary">
<color red="0.54117647058823526" green="0.4823529411764706" blue="0.68235294117647061" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>

1
elpha-ios/Configuration.swift

@ -12,6 +12,7 @@ struct Config {
static let clientName = "xyz.elpha.elpha-ios"
static let clientDisplayName = "Elpha"
static let clientWebsite = "https://elpha.xyz"
static let clientRedirectURI = "elpha://oauth"
static let instancesServiceURL = "https://instances.social"
static let instancesServiceListEndpoint = "/api/1.0/instances/list"

2
elpha-ios/MastodonAPI.swift

@ -342,7 +342,7 @@ class MastodonAPI {
let requestURL = serverURL.appendingPathComponent("api/v1/apps")
let parameters: Parameters = [
"client_name": Config.clientDisplayName,
"redirect_uris": "elpha://oauth",
"redirect_uris": Config.clientRedirectURI,
"scopes": "read write follow",
"website": Config.clientWebsite,
]

2
elpha-ios/StatusTableViewController.swift

@ -317,7 +317,7 @@ extension StatusTableViewController: StatusViewDelegate {
}
}
func loadMoreTapped(pagination: PaginationItem) {
func loadMoreTapped(status: StatusMO, direction: PaginationDirection) {
}
}

13
elpha-ios/StatusView.swift

@ -14,7 +14,7 @@ protocol StatusViewDelegate {
func statusTapped(status: StatusMO)
func favoriteTapped(status: StatusMO)
func reblogTapped(status: StatusMO)
func loadMoreTapped(pagination: PaginationItem)
func loadMoreTapped(status: StatusMO, direction: PaginationDirection)
}
class StatusView: UIView {
@ -93,8 +93,17 @@ class StatusView: UIView {
}
}
@IBAction func topLoadMoreViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.loadMoreTapped(status: status, direction: .prev)
}
}
@IBAction func bottomLoadMoreViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.loadMoreTapped(status: status, direction: .next)
}
}
@objc func reveal(sender: UITapGestureRecognizer) {
if let status = status {

18
elpha-ios/StatusView.xib

@ -75,6 +75,7 @@
</label>
</subviews>
<color key="backgroundColor" name="Secondary"/>
<gestureRecognizers/>
<constraints>
<constraint firstItem="701-8A-mp6" firstAttribute="centerY" secondItem="fjq-Ff-PVL" secondAttribute="centerY" id="Exh-9G-osC"/>
<constraint firstItem="701-8A-mp6" firstAttribute="leading" secondItem="IRZ-QQ-s88" secondAttribute="trailing" constant="10" id="GLS-PV-V9a"/>
@ -82,6 +83,9 @@
<constraint firstItem="IRZ-QQ-s88" firstAttribute="centerY" secondItem="fjq-Ff-PVL" secondAttribute="centerY" id="uiy-Kk-Nb7"/>
<constraint firstAttribute="height" priority="999" constant="50" id="zaz-CL-dbD"/>
</constraints>
<connections>
<outletCollection property="gestureRecognizers" destination="7gE-ee-xzN" appends="YES" id="tk2-yl-qwQ"/>
</connections>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="Gnt-jG-tVj">
<rect key="frame" x="0.0" y="55" width="375" height="100"/>
@ -456,6 +460,7 @@
</label>
</subviews>
<color key="backgroundColor" name="Secondary"/>
<gestureRecognizers/>
<constraints>
<constraint firstItem="zEk-jb-LHL" firstAttribute="leading" secondItem="0aT-X9-NYg" secondAttribute="leading" constant="15" id="9Gu-BD-Bmd"/>
<constraint firstAttribute="height" priority="999" constant="50" id="QLd-0c-UI5"/>
@ -463,6 +468,9 @@
<constraint firstItem="znl-Zz-bfs" firstAttribute="leading" secondItem="zEk-jb-LHL" secondAttribute="trailing" constant="10" id="a1v-10-RvI"/>
<constraint firstItem="znl-Zz-bfs" firstAttribute="centerY" secondItem="0aT-X9-NYg" secondAttribute="centerY" id="vyP-n3-i6x"/>
</constraints>
<connections>
<outletCollection property="gestureRecognizers" destination="o5u-JP-Bmz" appends="YES" id="Wxi-2I-YXA"/>
</connections>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="m4t-ve-E78">
<rect key="frame" x="0.0" y="860" width="375" height="5"/>
@ -516,6 +524,16 @@
<action selector="spoilerImageTapped:" destination="-1" id="3mz-UA-QEJ"/>
</connections>
</tapGestureRecognizer>
<tapGestureRecognizer id="o5u-JP-Bmz">
<connections>
<action selector="bottomLoadMoreViewTapped:" destination="-1" id="Pqp-f4-rDs"/>
</connections>
</tapGestureRecognizer>
<tapGestureRecognizer id="7gE-ee-xzN">
<connections>
<action selector="topLoadMoreViewTapped:" destination="-1" id="VI5-n7-v8p"/>
</connections>
</tapGestureRecognizer>
</objects>
<resources>
<image name="Alert" width="22" height="22"/>

54
elpha-ios/TimelineTableViewController.swift

@ -79,9 +79,10 @@ class TimelineTableViewController: UITableViewController, TimelinesViewControlle
}
@objc func compose() {
let alertController = UIAlertController(title: "Compose", message: "Toot", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
present(alertController, animated: true)
// let alertController = UIAlertController(title: "Compose", message: "Toot", preferredStyle: .alert)
// alertController.addAction(UIAlertAction(title: "OK", style: .default, handler: nil))
// present(alertController, animated: true)
AlertManager.shared.show(message: "Test message")
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
@ -424,44 +425,17 @@ extension TimelineTableViewController: StatusViewDelegate {
}
}
func loadMoreTapped(pagination: PaginationItem) {
fetchTimeline(withPagination: pagination) { error in
if error != nil {
print("\(String(describing: error))")
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 {
print("\(String(describing: error))")
}
}
}
}
}
}
}
extension TimelineTableViewController {
func newStatusView() -> NewStatusesView {
let newStatusesView = NewStatusesView()
newStatusesView.translatesAutoresizingMaskIntoConstraints = false
let blurEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffect.Style.prominent))
blurEffectView.translatesAutoresizingMaskIntoConstraints = false
blurEffectView.contentView.addSubview(newStatusesView)
blurEffectView.layer.cornerRadius = 10
blurEffectView.layer.masksToBounds = true
NSLayoutConstraint.activate([
newStatusesView.leadingAnchor.constraint(equalTo: blurEffectView.leadingAnchor),
newStatusesView.trailingAnchor.constraint(equalTo: blurEffectView.trailingAnchor),
newStatusesView.topAnchor.constraint(equalTo: blurEffectView.topAnchor),
newStatusesView.bottomAnchor.constraint(equalTo: blurEffectView.bottomAnchor),
])
view.addSubview(blurEffectView)
let bottomLayoutConstraint = blurEffectView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 100)
NSLayoutConstraint.activate([
blurEffectView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20),
blurEffectView.widthAnchor.constraint(equalToConstant: 200),
blurEffectView.heightAnchor.constraint(equalToConstant: 50),
bottomLayoutConstraint,
])
return newStatusesView
}
}
Loading…
Cancel
Save