Browse Source

Development

master
Dwayne Harris 6 years ago
parent
commit
f6900dbb4b
  1. 8
      elpha-ios.xcodeproj/project.pbxproj
  2. 9
      elpha-ios/AccountTableViewController.swift
  3. 6
      elpha-ios/AttachmentsManager.swift
  4. 56
      elpha-ios/Base.lproj/Main.storyboard
  5. 4
      elpha-ios/Elpha.xcdatamodeld/Elpha.xcdatamodel/contents
  6. 17
      elpha-ios/MainStatusTableViewCell.swift
  7. 13
      elpha-ios/StatusTableViewCell.swift
  8. 235
      elpha-ios/StatusTableViewController.swift
  9. 9
      elpha-ios/StatusView.swift
  10. 30
      elpha-ios/StatusView.xib
  11. 10
      elpha-ios/TimelineTableViewController.swift

8
elpha-ios.xcodeproj/project.pbxproj

@ -19,6 +19,8 @@
151AD4E621689A0F00F07403 /* Alamofire.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 157405C3215890BC00EEAAEB /* Alamofire.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
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 */; };
156FF051217683270074D9CA /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 156FF050217683270074D9CA /* StatusTableViewCell.swift */; };
157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405A72150588A00EEAAEB /* InstanceViewController.swift */; };
157405B12151A5DA00EEAAEB /* README.md in Resources */ = {isa = PBXBuildFile; fileRef = 157405AF2151A5DA00EEAAEB /* README.md */; };
157405B42151A93E00EEAAEB /* InstancesDataManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 157405B32151A93E00EEAAEB /* InstancesDataManager.swift */; };
@ -289,6 +291,8 @@
1517EA6F2159D72200DE80D6 /* AlamofireImage.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = AlamofireImage.xcodeproj; path = Frameworks/AlamofireImage/AlamofireImage.xcodeproj; 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>"; };
156FF050217683270074D9CA /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = "<group>"; };
157405A72150588A00EEAAEB /* InstanceViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstanceViewController.swift; sourceTree = "<group>"; };
157405AF2151A5DA00EEAAEB /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = "<group>"; };
157405B32151A93E00EEAAEB /* InstancesDataManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstancesDataManager.swift; sourceTree = "<group>"; };
@ -391,6 +395,8 @@
children = (
156FF014217289380074D9CA /* AccountTableViewCell.swift */,
159048AE214F5015004F4014 /* InstancesTableViewCell.swift */,
156FF04E2175CDBC0074D9CA /* MainStatusTableViewCell.swift */,
156FF050217683270074D9CA /* StatusTableViewCell.swift */,
15BB72AA2171A8D4002F1FA4 /* TimelinesTableViewCell.swift */,
159026AD2162CF5600D362DD /* TimelineTableViewCell.swift */,
);
@ -823,12 +829,14 @@
15960E7521322BF800C38CE9 /* KeychainWrapper.swift in Sources */,
157405A82150588A00EEAAEB /* InstanceViewController.swift in Sources */,
15960E7321322BC700C38CE9 /* KeychainItemAccessibility.swift in Sources */,
156FF051217683270074D9CA /* StatusTableViewCell.swift in Sources */,
159026D02163069600D362DD /* Date+TimeAgo.swift in Sources */,
15A79B43215EB959007A326E /* CoreDataManager.swift in Sources */,
15BB72AB2171A8D4002F1FA4 /* TimelinesTableViewCell.swift in Sources */,
1574148D2169AD0100C841BD /* AttachmentsManager.swift in Sources */,
156FF015217289380074D9CA /* AccountTableViewCell.swift in Sources */,
15960E822136668500C38CE9 /* TimelinesNavigationController.swift in Sources */,
156FF04F2175CDBC0074D9CA /* MainStatusTableViewCell.swift in Sources */,
159026AE2162CF5600D362DD /* TimelineTableViewCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

9
elpha-ios/AccountTableViewController.swift

@ -277,4 +277,13 @@ extension AccountTableViewController: StatusViewDelegate {
self.navigationController?.pushViewController(controller, animated: true)
}
}
func statusTapped(status: StatusMO) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController {
controller.status = status
self.navigationController?.pushViewController(controller, animated: true)
}
}
}

6
elpha-ios/AttachmentsManager.swift

@ -46,8 +46,6 @@ class AttachmentsManager {
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
imageView.widthAnchor.constraint(equalToConstant: view.frame.width),
imageView.heightAnchor.constraint(equalToConstant: view.frame.width),
])
case 2:
let filter = AspectScaledToFillSizeFilter(size: CGSize(width: halfWidth, height: view.frame.width))
@ -72,7 +70,6 @@ class AttachmentsManager {
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
imageView.widthAnchor.constraint(equalToConstant: halfWidth),
imageView.heightAnchor.constraint(equalToConstant: view.frame.width),
])
}
@ -107,7 +104,6 @@ class AttachmentsManager {
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
imageView.widthAnchor.constraint(equalToConstant: halfWidth),
imageView.heightAnchor.constraint(equalToConstant: view.frame.width),
])
} else {
NSLayoutConstraint.activate([
@ -143,10 +139,12 @@ class AttachmentsManager {
view.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
/*
NSLayoutConstraint.activate([
imageView.widthAnchor.constraint(equalToConstant: halfWidth),
imageView.heightAnchor.constraint(equalToConstant: halfWidth),
])
*/
}
NSLayoutConstraint.activate([

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

@ -874,16 +874,16 @@
<scene sceneID="E93-GN-Ar4">
<objects>
<tableViewController storyboardIdentifier="StatusTableViewController" id="RAJ-ub-len" customClass="StatusTableViewController" customModule="elpha_ios" 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="3Kx-zr-iiy">
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="grouped" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="18" sectionFooterHeight="18" id="3Kx-zr-iiy">
<rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="backgroundColor" cocoaTouchSystemColor="groupTableViewBackgroundColor"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="MainStatusTableViewCell" rowHeight="223" id="8ys-Fm-1Yg">
<rect key="frame" x="0.0" y="28" width="414" height="223"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="MainStatusTableViewCell" rowHeight="200" id="8ys-Fm-1Yg" customClass="MainStatusTableViewCell" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="55.5" width="414" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="8ys-Fm-1Yg" id="Hj7-kC-H7L">
<rect key="frame" x="0.0" y="0.0" width="414" height="222.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="200"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="7I8-6E-s1Q">
@ -922,8 +922,8 @@
<constraint firstAttribute="height" constant="60" id="sS1-Yz-Efq"/>
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AT3-0d-kQ3">
<rect key="frame" x="20" y="86" width="374" height="21"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="AT3-0d-kQ3">
<rect key="frame" x="20" y="86" width="374" height="95"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" name="Text"/>
<nil key="highlightedColor"/>
@ -933,31 +933,41 @@
<constraint firstAttribute="trailingMargin" secondItem="7I8-6E-s1Q" secondAttribute="trailing" id="5hL-Ma-O1w"/>
<constraint firstAttribute="trailingMargin" secondItem="AT3-0d-kQ3" secondAttribute="trailing" id="6Wd-QF-Ar9"/>
<constraint firstItem="7I8-6E-s1Q" firstAttribute="leading" secondItem="Hj7-kC-H7L" secondAttribute="leadingMargin" id="7SB-qd-J9a"/>
<constraint firstAttribute="bottomMargin" secondItem="AT3-0d-kQ3" secondAttribute="bottom" constant="8" id="BXc-hI-FGC"/>
<constraint firstItem="7I8-6E-s1Q" firstAttribute="top" secondItem="Hj7-kC-H7L" secondAttribute="topMargin" id="LFk-zl-zWh"/>
<constraint firstItem="AT3-0d-kQ3" firstAttribute="leading" secondItem="Hj7-kC-H7L" secondAttribute="leadingMargin" id="uff-zi-rPT"/>
<constraint firstItem="AT3-0d-kQ3" firstAttribute="top" secondItem="7I8-6E-s1Q" secondAttribute="bottom" constant="15" id="xNg-ZQ-vkn"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="avatarImageView" destination="LHS-vw-fZE" id="PpS-hb-Hes"/>
<outlet property="contentLabel" destination="AT3-0d-kQ3" id="c7N-3x-fJ9"/>
<outlet property="displayNameLabel" destination="vDe-e6-p1i" id="jxi-k7-Zll"/>
<outlet property="usernameLabel" destination="8fE-Hr-jgf" id="hiJ-he-cm4"/>
</connections>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="StatusTableViewCell" rowHeight="121" id="cLF-Rc-b4K">
<rect key="frame" x="0.0" y="251" width="414" height="121"/>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="StatusTableViewCell" rowHeight="120" id="cLF-Rc-b4K" customClass="StatusTableViewCell" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="255.5" width="414" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="cLF-Rc-b4K" id="jhE-cB-Cj1">
<rect key="frame" x="0.0" y="0.0" width="414" height="120.5"/>
<rect key="frame" x="0.0" y="0.0" width="414" height="120"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fRl-xT-b9t">
<rect key="frame" x="20" y="11" width="374" height="99"/>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="fRl-xT-b9t" customClass="StatusView" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="0.0" width="414" height="120"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</view>
</subviews>
<constraints>
<constraint firstItem="fRl-xT-b9t" firstAttribute="leading" secondItem="jhE-cB-Cj1" secondAttribute="leadingMargin" id="2vX-eS-RPz"/>
<constraint firstItem="fRl-xT-b9t" firstAttribute="top" secondItem="jhE-cB-Cj1" secondAttribute="topMargin" id="MDD-gu-JCo"/>
<constraint firstAttribute="trailingMargin" secondItem="fRl-xT-b9t" secondAttribute="trailing" id="cqF-mA-SXc"/>
<constraint firstAttribute="bottomMargin" secondItem="fRl-xT-b9t" secondAttribute="bottom" id="eFf-oz-Kvz"/>
<constraint firstItem="fRl-xT-b9t" firstAttribute="leading" secondItem="jhE-cB-Cj1" secondAttribute="leading" id="2vX-eS-RPz"/>
<constraint firstItem="fRl-xT-b9t" firstAttribute="top" secondItem="jhE-cB-Cj1" secondAttribute="top" id="MDD-gu-JCo"/>
<constraint firstAttribute="trailing" secondItem="fRl-xT-b9t" secondAttribute="trailing" id="cqF-mA-SXc"/>
<constraint firstAttribute="bottom" secondItem="fRl-xT-b9t" secondAttribute="bottom" id="eFf-oz-Kvz"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="statusView" destination="fRl-xT-b9t" id="8iV-CU-O47"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
@ -965,6 +975,17 @@
<outlet property="delegate" destination="RAJ-ub-len" id="P31-wp-SuL"/>
</connections>
</tableView>
<refreshControl key="refreshControl" opaque="NO" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" enabled="NO" contentHorizontalAlignment="center" contentVerticalAlignment="center" id="1F2-ct-Zy0">
<autoresizingMask key="autoresizingMask"/>
<attributedString key="attributedTitle">
<fragment content="Loading...">
<attributes>
<font key="NSFont" size="13" name=".AppleSystemUIFont"/>
<paragraphStyle key="NSParagraphStyle" alignment="center" lineBreakMode="wordWrapping" baseWritingDirection="natural" tighteningFactorForTruncation="0.0"/>
</attributes>
</fragment>
</attributedString>
</refreshControl>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="3LK-Q6-p6V" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
@ -1039,5 +1060,8 @@
<namedColor name="Text">
<color red="0.090196078431372548" green="0.047058823529411764" blue="0.28627450980392155" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
<namedColor name="Text">
<color red="0.090196078431372548" green="0.047058823529411764" blue="0.28627450980392155" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
</namedColor>
</resources>
</document>

4
elpha-ios/Elpha.xcdatamodeld/Elpha.xcdatamodel/contents

@ -137,8 +137,10 @@
<attribute name="url" optional="YES" attributeType="URI" syncable="YES"/>
<attribute name="visibility" optional="YES" attributeType="String" syncable="YES"/>
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Account" inverseName="statuses" inverseEntity="Account" syncable="YES"/>
<relationship name="ancestors" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="descendants" inverseEntity="Status" syncable="YES"/>
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="App" inverseName="statuses" inverseEntity="App" syncable="YES"/>
<relationship name="attachments" optional="YES" toMany="YES" deletionRule="Nullify" ordered="YES" destinationEntity="Attachment" inverseName="status" inverseEntity="Attachment" syncable="YES"/>
<relationship name="descendants" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="ancestors" inverseEntity="Status" syncable="YES"/>
<relationship name="emojis" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Emoji" inverseName="statuses" inverseEntity="Emoji" syncable="YES"/>
<relationship name="mentions" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Mention" inverseName="status" inverseEntity="Mention" syncable="YES"/>
<relationship name="reblog" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status" inverseName="reblogs" inverseEntity="Status" syncable="YES"/>
@ -169,7 +171,7 @@
<element name="ISLanguage" positionX="-286.21875" positionY="512.6171875" width="128" height="75"/>
<element name="Mention" positionX="-441" positionY="234" width="128" height="135"/>
<element name="Session" positionX="-445.046875" positionY="277.31640625" width="128" height="150"/>
<element name="Status" positionX="-459" positionY="216" width="128" height="435"/>
<element name="Status" positionX="-459" positionY="216" width="128" height="465"/>
<element name="Tag" positionX="-432" positionY="243" width="128" height="90"/>
<element name="Timeline" positionX="-468" positionY="207" width="128" height="120"/>
</elements>

17
elpha-ios/MainStatusTableViewCell.swift

@ -0,0 +1,17 @@
//
// MainStatusTableViewCell.swift
// elpha-ios
//
// Created by Dwayne Harris on 10/16/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import UIKit
class MainStatusTableViewCell: UITableViewCell {
@IBOutlet var avatarImageView: UIImageView!
@IBOutlet var displayNameLabel: UILabel!
@IBOutlet var usernameLabel: UILabel!
@IBOutlet var contentLabel: UILabel!
}

13
elpha-ios/StatusTableViewCell.swift

@ -0,0 +1,13 @@
//
// StatusTableViewCell.swift
// elpha-ios
//
// Created by Dwayne Harris on 10/16/18.
// Copyright © 2018 Elpha. All rights reserved.
//
import UIKit
class StatusTableViewCell: UITableViewCell {
@IBOutlet var statusView: StatusView!
}

235
elpha-ios/StatusTableViewController.swift

@ -6,8 +6,243 @@
// Copyright © 2018 Elpha. All rights reserved.
//
import AlamofireImage
import CoreData
import MastodonKit
import UIKit
enum StatusType {
case ancestor
case status
case descendant
}
class StatusTableViewController: UITableViewController {
public var status: StatusMO? = nil
private var statuses: Dictionary<StatusType, [StatusMO]> = [:]
var loading: Bool = false {
didSet {
DispatchQueue.main.async {
if self.loading {
self.refreshControl?.beginRefreshing()
} else {
self.refreshControl?.endRefreshing()
}
}
}
}
override func viewDidLoad() {
super.viewDidLoad()
// navigationItem.title = "Toot"
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
fetchStatuses { error in
if error != nil {
print("\(String(describing: error))")
}
}
}
func fetchStatuses(completion: @escaping (Error?) -> Void) {
guard let client = AuthenticationManager.shared.mkClient else {
completion(nil)
return
}
if let status = status {
loading = true
let statusRequest = Statuses.status(id: status.id!)
let contextRequest = Statuses.context(id: status.id!)
client.run(statusRequest) { result in
switch result {
case .success(let remoteStatus, _):
DispatchQueue.main.async {
_ = MastodonDataManager.upsertStatus(remoteStatus)
}
client.run(contextRequest) { result in
switch result {
case .success(let context, _):
DispatchQueue.main.async {
context.ancestors.forEach { remoteAncestor in
let ancestor = MastodonDataManager.upsertStatus(remoteAncestor)
status.addToAncestors(ancestor!.model)
}
context.ancestors.forEach { remoteDescendant in
let descendant = MastodonDataManager.upsertStatus(remoteDescendant)
status.addToDescendants(descendant!.model)
}
CoreDataManager.shared.saveContext()
self.loading = false
self.loadStatuses()
self.tableView.reloadData()
completion(nil)
}
case .failure(let error):
completion(error)
}
}
case .failure(let error):
completion(error)
}
}
}
}
func loadStatuses() {
print("Running loadStatuses()")
guard let status = status else {
return
}
let request = NSFetchRequest<StatusMO>(entityName: "Status")
request.predicate = NSPredicate(format: "id == %@ OR ANY ancestors == %@ OR ANY descendants == %@", status.id!, status, status)
request.sortDescriptors = [
NSSortDescriptor(key: "createdAt", ascending: false),
]
do {
let statuses = try CoreDataManager.shared.context.fetch(request)
self.statuses = Dictionary(grouping: statuses) { s -> StatusType in
switch s.createdAt!.compare(status.createdAt!) {
case .orderedSame:
return .status
case .orderedAscending:
return .ancestor
case .orderedDescending:
return .descendant
}
}
} catch {
print("\(error)")
}
}
}
extension StatusTableViewController {
override func numberOfSections(in tableView: UITableView) -> Int {
return statuses.count
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
if statuses.count == 1 {
return nil
}
switch Array(statuses.keys)[section] {
case .status:
return "Toot"
case .ancestor:
return "In Reply To"
case .descendant:
return "Replies"
}
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return Array(statuses.values)[section].count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let statuses = Array(self.statuses.values)[indexPath.section]
let status = statuses[indexPath.row]
if status == self.status {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "MainStatusTableViewCell", for: indexPath) as? MainStatusTableViewCell else {
fatalError("Unable to find reusable cell")
}
let avatarFilter = AspectScaledToFillSizeWithRoundedCornersFilter(
size: CGSize(width: 40.0, height: 40.0),
radius: 30.0,
divideRadiusByImageScale: true
)
func updateAccountView(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
}
}
if let reblog = status.reblog {
updateAccountView(status: reblog)
} else {
updateAccountView(status: status)
}
if let content = status.content {
do {
let styledContent = "<style>html * { font-size: 15px; color: #170c49; font-family: -apple-system } p { margin: 0; padding: 0 }</style> \(content)"
let attributedText = try NSAttributedString(
data: styledContent.data(using: String.Encoding.unicode, allowLossyConversion: true)!,
options: [.documentType: NSAttributedString.DocumentType.html],
documentAttributes: nil
)
cell.contentLabel.attributedText = attributedText
} catch {
print("\(error)")
}
}
return cell
} else {
guard let cell = tableView.dequeueReusableCell(withIdentifier: "StatusTableViewCell", for: indexPath) as? StatusTableViewCell else {
fatalError("Unable to find reusable cell")
}
cell.statusView.delegate = self
cell.statusView.update(withStatus: status)
cell.statusView.replyView.isHidden = true
if !loading {
let statusAge = Calendar.current.dateComponents([.minute], from: status.fetchedAt!, to: Date())
let stale = statusAge.minute! > 30
if stale {
fetchStatuses { error in
if error != nil {
print("\(String(describing: error))")
}
}
}
}
return cell
}
}
}
extension StatusTableViewController: StatusViewDelegate {
func accountTapped(account: AccountMO) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let controller = storyboard.instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController {
controller.account = account
self.navigationController?.pushViewController(controller, animated: true)
}
}
func statusTapped(status: StatusMO) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController {
controller.status = status
self.navigationController?.pushViewController(controller, animated: true)
}
}
}

9
elpha-ios/StatusView.swift

@ -11,6 +11,7 @@ import UIKit
protocol StatusViewDelegate {
func accountTapped(account: AccountMO)
func statusTapped(status: StatusMO)
}
class StatusView: UIView {
@ -67,6 +68,13 @@ class StatusView: UIView {
}
}
@IBAction func mainViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.statusTapped(status: status)
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
@ -93,7 +101,6 @@ class StatusView: UIView {
bottomDividerView.isHidden = false
attachmentsView.backgroundColor = UIColor.white
attachmentsHeightConstraint.constant = frame.width
attachmentsView.isHidden = true
let avatarFilter = AspectScaledToFillSizeWithRoundedCornersFilter(

30
elpha-ios/StatusView.xib

@ -12,7 +12,6 @@
<objects>
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="StatusView" customModule="elpha_ios" customModuleProvider="target">
<connections>
<outlet property="attachmentsHeightConstraint" destination="nbr-i2-Chb" id="osy-bg-2Ny"/>
<outlet property="attachmentsView" destination="XuS-iF-YYL" id="HFB-cz-e3h"/>
<outlet property="avatarImageView" destination="i10-Gq-NR9" id="xe9-ci-dSr"/>
<outlet property="boostAvatarImageView" destination="ecc-6t-6K0" id="Z09-BM-AEA"/>
@ -40,11 +39,11 @@
</placeholder>
<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"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="838"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="7Og-IU-seR">
<rect key="frame" x="0.0" y="20" width="375" height="647"/>
<rect key="frame" x="0.0" y="20" width="375" height="818"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="bg1-Q4-Ru5">
<rect key="frame" x="0.0" y="0.0" width="375" height="5"/>
@ -190,10 +189,10 @@
</connections>
</view>
<view contentMode="scaleToFill" verticalHuggingPriority="249" translatesAutoresizingMaskIntoConstraints="NO" id="cAR-YB-u2k">
<rect key="frame" x="0.0" y="205" width="375" height="376"/>
<rect key="frame" x="0.0" y="205" width="375" height="173"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WPF-Oe-N2r">
<rect key="frame" x="8" y="93" width="359" height="275"/>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="249" text="Content" textAlignment="natural" lineBreakMode="wordWrap" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="WPF-Oe-N2r">
<rect key="frame" x="8" y="93" width="359" height="72"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" name="Text"/>
<nil key="highlightedColor"/>
@ -240,6 +239,7 @@
</view>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<gestureRecognizers/>
<constraints>
<constraint firstAttribute="bottom" secondItem="WPF-Oe-N2r" secondAttribute="bottom" constant="8" id="60R-bR-ZXD"/>
<constraint firstAttribute="trailing" secondItem="50m-cW-QIF" secondAttribute="trailing" constant="8" id="FxM-Hx-2Do"/>
@ -249,16 +249,19 @@
<constraint firstAttribute="trailing" secondItem="WPF-Oe-N2r" secondAttribute="trailing" constant="8" id="vxV-3b-ytI"/>
<constraint firstItem="WPF-Oe-N2r" firstAttribute="leading" secondItem="cAR-YB-u2k" secondAttribute="leading" constant="8" id="wqO-6z-tPD"/>
</constraints>
<connections>
<outletCollection property="gestureRecognizers" destination="9fc-Py-yTV" appends="YES" id="nDQ-45-6W2"/>
</connections>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="XuS-iF-YYL">
<rect key="frame" x="0.0" y="581" width="375" height="1"/>
<rect key="frame" x="0.0" y="378" width="375" height="375"/>
<color key="backgroundColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="height" constant="1" id="nbr-i2-Chb"/>
<constraint firstAttribute="width" secondItem="XuS-iF-YYL" secondAttribute="height" multiplier="1:1" id="fuy-4s-Ojn"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="y5N-A7-27p">
<rect key="frame" x="0.0" y="582" width="375" height="60"/>
<rect key="frame" x="0.0" y="753" width="375" height="60"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="pJk-g2-yyR">
<rect key="frame" x="8" y="15" width="155" height="30"/>
@ -384,7 +387,7 @@
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="m4t-ve-E78">
<rect key="frame" x="0.0" y="642" width="375" height="5"/>
<rect key="frame" x="0.0" y="813" width="375" height="5"/>
<color key="backgroundColor" red="0.93725490199999995" green="0.93725490199999995" blue="0.93725490199999995" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<constraints>
<constraint firstAttribute="height" constant="5" id="QFa-Y9-r5a"/>
@ -404,7 +407,7 @@
<nil key="simulatedBottomBarMetrics"/>
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
<viewLayoutGuide key="safeArea" id="vUN-kp-3ea"/>
<point key="canvasLocation" x="53.600000000000001" y="48.125937031484263"/>
<point key="canvasLocation" x="53.600000000000001" y="125.03748125937032"/>
</view>
<tapGestureRecognizer id="2h0-to-AXg">
<connections>
@ -421,6 +424,11 @@
<action selector="accountViewTapped:" destination="-1" id="juK-EX-PYY"/>
</connections>
</tapGestureRecognizer>
<tapGestureRecognizer id="9fc-Py-yTV">
<connections>
<action selector="mainViewTapped:" destination="-1" id="tEa-rG-C4L"/>
</connections>
</tapGestureRecognizer>
</objects>
<resources>
<image name="Boost Regular" width="20" height="24"/>

10
elpha-ios/TimelineTableViewController.swift

@ -261,6 +261,7 @@ extension TimelineTableViewController {
cell.statusView.delegate = self
cell.statusView.update(withStatus: status)
cell.statusView.topDividerView.isHidden = indexPath.row == 0
if !loading {
let statusAge = Calendar.current.dateComponents([.minute], from: status.fetchedAt!, to: Date())
@ -290,6 +291,15 @@ extension TimelineTableViewController: StatusViewDelegate {
self.navigationController?.pushViewController(controller, animated: true)
}
}
func statusTapped(status: StatusMO) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let controller = storyboard.instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController {
controller.status = status
self.navigationController?.pushViewController(controller, animated: true)
}
}
}
extension TimelineTableViewController {

Loading…
Cancel
Save