Multiple timeline views

This commit is contained in:
Shadowfacts 2018-08-21 17:17:25 -04:00
parent 7db0f4ff77
commit 21c54c2759
7 changed files with 107 additions and 55 deletions

View File

@ -7,6 +7,8 @@
objects = {
/* Begin PBXBuildFile section */
04DACE8A212CA6B7009840C4 /* Timeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE89212CA6B7009840C4 /* Timeline.swift */; };
04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */; };
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AAC2128D88B005A6F37 /* LocalData.swift */; };
D64D0AAF2128D954005A6F37 /* Onboarding.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */; };
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */; };
@ -14,7 +16,6 @@
D6BED170212663DA00F02DA0 /* SwiftSoup.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6BED16E212663DA00F02DA0 /* SwiftSoup.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BED173212667E900F02DA0 /* StatusTableViewCell.swift */; };
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */; };
D6D4DDD2212518A000E1C4BB /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDD1212518A000E1C4BB /* ViewController.swift */; };
D6D4DDD5212518A000E1C4BB /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD3212518A000E1C4BB /* Main.storyboard */; };
D6D4DDD7212518A200E1C4BB /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD6212518A200E1C4BB /* Assets.xcassets */; };
D6D4DDDA212518A200E1C4BB /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */; };
@ -22,8 +23,8 @@
D6D4DDF0212518A200E1C4BB /* TuskerUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */; };
D6F953E7212519A400CF0F2B /* MastodonKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = D6F953E6212519A400CF0F2B /* MastodonKit.framework */; };
D6F953E8212519A400CF0F2B /* MastodonKit.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = D6F953E6212519A400CF0F2B /* MastodonKit.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
D6F953EC212519E700CF0F2B /* StatusesTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EB212519E700CF0F2B /* StatusesTableViewController.swift */; };
D6F953EE21251A0700CF0F2B /* Statuses.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6F953ED21251A0700CF0F2B /* Statuses.storyboard */; };
D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */; };
D6F953EE21251A0700CF0F2B /* Timeline.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D6F953ED21251A0700CF0F2B /* Timeline.storyboard */; };
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6F953EF21251A2900CF0F2B /* MastodonController.swift */; };
/* End PBXBuildFile section */
@ -60,6 +61,8 @@
/* End PBXCopyFilesBuildPhase section */
/* Begin PBXFileReference section */
04DACE89212CA6B7009840C4 /* Timeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Timeline.swift; sourceTree = "<group>"; };
04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainTabBarViewController.swift; sourceTree = "<group>"; };
D64D0AAC2128D88B005A6F37 /* LocalData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LocalData.swift; sourceTree = "<group>"; };
D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Onboarding.storyboard; sourceTree = "<group>"; };
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewController.swift; sourceTree = "<group>"; };
@ -67,7 +70,6 @@
D6BED173212667E900F02DA0 /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = "<group>"; };
D6D4DDCC212518A000E1C4BB /* Tusker.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Tusker.app; sourceTree = BUILT_PRODUCTS_DIR; };
D6D4DDCF212518A000E1C4BB /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
D6D4DDD1212518A000E1C4BB /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = "<group>"; };
D6D4DDD4212518A000E1C4BB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
D6D4DDD6212518A200E1C4BB /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
D6D4DDD9212518A200E1C4BB /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
@ -79,8 +81,8 @@
D6D4DDEF212518A200E1C4BB /* TuskerUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TuskerUITests.swift; sourceTree = "<group>"; };
D6D4DDF1212518A200E1C4BB /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
D6F953E6212519A400CF0F2B /* MastodonKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = MastodonKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D6F953EB212519E700CF0F2B /* StatusesTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusesTableViewController.swift; sourceTree = "<group>"; };
D6F953ED21251A0700CF0F2B /* Statuses.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Statuses.storyboard; sourceTree = "<group>"; };
D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineTableViewController.swift; sourceTree = "<group>"; };
D6F953ED21251A0700CF0F2B /* Timeline.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = Timeline.storyboard; sourceTree = "<group>"; };
D6F953EF21251A2900CF0F2B /* MastodonController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonController.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
@ -153,6 +155,7 @@
D6D4DDD6212518A200E1C4BB /* Assets.xcassets */,
D6D4DDD8212518A200E1C4BB /* LaunchScreen.storyboard */,
D6D4DDDB212518A200E1C4BB /* Info.plist */,
04DACE89212CA6B7009840C4 /* Timeline.swift */,
);
path = Tusker;
sourceTree = "<group>";
@ -178,9 +181,9 @@
D6F953E9212519B800CF0F2B /* View Controllers */ = {
isa = PBXGroup;
children = (
D6D4DDD1212518A000E1C4BB /* ViewController.swift */,
D6F953EB212519E700CF0F2B /* StatusesTableViewController.swift */,
D6F953EB212519E700CF0F2B /* TimelineTableViewController.swift */,
D64D0AB02128D9AE005A6F37 /* OnboardingViewController.swift */,
04DACE8B212CB14B009840C4 /* MainTabBarViewController.swift */,
);
path = "View Controllers";
sourceTree = "<group>";
@ -189,7 +192,7 @@
isa = PBXGroup;
children = (
D6D4DDD3212518A000E1C4BB /* Main.storyboard */,
D6F953ED21251A0700CF0F2B /* Statuses.storyboard */,
D6F953ED21251A0700CF0F2B /* Timeline.storyboard */,
D64D0AAE2128D954005A6F37 /* Onboarding.storyboard */,
);
path = Storyboards;
@ -311,7 +314,7 @@
D6D4DDDA212518A200E1C4BB /* LaunchScreen.storyboard in Resources */,
D64D0AAF2128D954005A6F37 /* Onboarding.storyboard in Resources */,
D6D4DDD7212518A200E1C4BB /* Assets.xcassets in Resources */,
D6F953EE21251A0700CF0F2B /* Statuses.storyboard in Resources */,
D6F953EE21251A0700CF0F2B /* Timeline.storyboard in Resources */,
D6D4DDD5212518A000E1C4BB /* Main.storyboard in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
@ -337,12 +340,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
04DACE8A212CA6B7009840C4 /* Timeline.swift in Sources */,
04DACE8C212CB14B009840C4 /* MainTabBarViewController.swift in Sources */,
D6F953F021251A2900CF0F2B /* MastodonController.swift in Sources */,
D6BED174212667E900F02DA0 /* StatusTableViewCell.swift in Sources */,
D6D4DDD2212518A000E1C4BB /* ViewController.swift in Sources */,
D64D0AAD2128D88B005A6F37 /* LocalData.swift in Sources */,
D64D0AB12128D9AE005A6F37 /* OnboardingViewController.swift in Sources */,
D6F953EC212519E700CF0F2B /* StatusesTableViewController.swift in Sources */,
D6F953EC212519E700CF0F2B /* TimelineTableViewController.swift in Sources */,
D6D4DDD0212518A000E1C4BB /* AppDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -8,28 +8,16 @@
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Statuses-->
<scene sceneID="OOu-1s-V6q">
<objects>
<viewControllerPlaceholder storyboardName="Statuses" id="7WZ-zC-GaE" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Item" id="qa8-hW-VHL"/>
</viewControllerPlaceholder>
<placeholder placeholderIdentifier="IBFirstResponder" id="O8i-mP-ani" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="385" y="-206"/>
</scene>
<!--Tab Bar Controller-->
<!--Main Tab Bar View Controller-->
<scene sceneID="ELt-Cr-gbC">
<objects>
<tabBarController automaticallyAdjustsScrollViewInsets="NO" id="hVq-Vu-bEj" sceneMemberID="viewController">
<tabBarController automaticallyAdjustsScrollViewInsets="NO" id="hVq-Vu-bEj" customClass="MainTabBarViewController" customModule="Tusker" customModuleProvider="target" sceneMemberID="viewController">
<toolbarItems/>
<tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="cjv-gb-Kie">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
<autoresizingMask key="autoresizingMask"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</tabBar>
<connections>
<segue destination="7WZ-zC-GaE" kind="relationship" relationship="viewControllers" id="q0Z-gP-JDT"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="1cN-fA-SM9" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>

View File

@ -8,10 +8,10 @@
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--Statuses Table View Controller-->
<!--Timeline Table View Controller-->
<scene sceneID="Ymv-6c-FNp">
<objects>
<tableViewController id="6nb-nb-cMm" customClass="StatusesTableViewController" customModule="Tusker" customModuleProvider="target" sceneMemberID="viewController">
<tableViewController id="6nb-nb-cMm" customClass="TimelineTableViewController" customModule="Tusker" customModuleProvider="target" sceneMemberID="viewController">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="MQI-VO-YZH">
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
@ -69,6 +69,7 @@
<navigationItem key="navigationItem" id="SQS-FM-ReS"/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
<refreshControl key="refreshControl" opaque="NO" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="K3b-fx-67z">
<rect key="frame" x="0.0" y="0.0" width="1000" height="1000"/>
<autoresizingMask key="autoresizingMask"/>
<connections>
<action selector="refreshStatuses:" destination="6nb-nb-cMm" eventType="valueChanged" id="ndM-Yv-ISu"/>
@ -79,11 +80,11 @@
</objects>
<point key="canvasLocation" x="800.79999999999995" y="-90.404797601199405"/>
</scene>
<!--Navigation Controller-->
<!--Item-->
<scene sceneID="yNQ-ej-ymp">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="CK3-h7-JHA" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" systemItem="mostRecent" id="dzR-Qn-Pf3"/>
<tabBarItem key="tabBarItem" title="Item" id="2mE-wd-ffe"/>
<toolbarItems/>
<simulatedTabBarMetrics key="simulatedBottomBarMetrics"/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="kM6-kS-XRr">

27
Tusker/Timeline.swift Normal file
View File

@ -0,0 +1,27 @@
//
// Timeline.swift
// Tusker
//
// Created by Shadowfactson 8/21/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import Foundation
import MastodonKit
enum Timeline {
case home, local, federated
func request(range: RequestRange = .default) -> Request<[Status]> {
switch self {
case .home:
return Timelines.home(range: range)
case .local:
return Timelines.public(local: true, range: range)
case .federated:
return Timelines.public(local: false, range: range)
}
}
}

View File

@ -0,0 +1,34 @@
//
// MainTabBarViewController.swift
// Tusker
//
// Created by Shadowfactson 8/21/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import UIKit
class MainTabBarViewController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
viewControllers = [
TimelineTableViewController.create(for: .home),
TimelineTableViewController.create(for: .federated),
TimelineTableViewController.create(for: .local)
]
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}

View File

@ -10,8 +10,26 @@ import UIKit
import MastodonKit
import SwiftSoup
class StatusesTableViewController: UITableViewController {
class TimelineTableViewController: UITableViewController {
static func create(for timeline: Timeline) -> UIViewController {
guard let navigationController = UIStoryboard(name: "Timeline", bundle: nil).instantiateInitialViewController() as? UINavigationController,
let timelineController = navigationController.topViewController as? TimelineTableViewController else { fatalError() }
timelineController.timeline = timeline
switch timeline {
case .home:
navigationController.tabBarItem.title = "Home"
case .local:
navigationController.tabBarItem.title = "Local"
case .federated:
navigationController.tabBarItem.title = "Federated"
}
return navigationController
}
var timeline: Timeline!
var statuses: [Status] = [] {
didSet {
DispatchQueue.main.async {
@ -25,7 +43,7 @@ class StatusesTableViewController: UITableViewController {
override func viewWillAppear(_ animated: Bool) {
guard MastodonController.shared.client?.accessToken != nil else { return }
MastodonController.shared.client.run(Timelines.home()) { result in
MastodonController.shared.client.run(timeline.request()) { result in
guard case let .success(statuses, pagination) = result else { fatalError() }
self.statuses = statuses
self.newer = pagination?.previous
@ -80,7 +98,7 @@ class StatusesTableViewController: UITableViewController {
if indexPath.row == statuses.count - 1 {
guard let older = older else { return }
MastodonController.shared.client.run(Timelines.home(range: older)) { result in
MastodonController.shared.client.run(timeline.request(range: older)) { result in
guard case let .success(newStatuses, pagination) = result else { fatalError() }
self.older = pagination?.next
self.statuses.append(contentsOf: newStatuses)
@ -91,7 +109,7 @@ class StatusesTableViewController: UITableViewController {
@IBAction func refreshStatuses(_ sender: Any) {
guard let newer = newer else { return }
MastodonController.shared.client.run(Timelines.home(range: newer)) { result in
MastodonController.shared.client.run(timeline.request(range: newer)) { result in
guard case let .success(newStatuses, pagination) = result else { fatalError() }
self.newer = pagination?.previous
self.statuses.insert(contentsOf: newStatuses, at: 0)

View File

@ -1,20 +0,0 @@
//
// ViewController.swift
// Tusker
//
// Created by Shadowfacts on 8/15/18.
// Copyright © 2018 Shadowfacts. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}