Browse Source

Fix things and clean up code

master
Dwayne Harris 6 years ago
parent
commit
d9c2956d00
  1. 22
      elpha-ios/AbstractStatusTableViewController.swift
  2. 35
      elpha-ios/AccountTableViewController.swift
  3. 4
      elpha-ios/AlertManager.swift
  4. 2
      elpha-ios/AlertView.swift
  5. 6
      elpha-ios/AppDelegate.swift
  6. 8
      elpha-ios/AttachmentManager.swift
  7. 2
      elpha-ios/AttachmentPageViewController.swift
  8. 2
      elpha-ios/AttachmentViewController.swift
  9. 18
      elpha-ios/AuthenticateViewController.swift
  10. 34
      elpha-ios/AuthenticationManager.swift
  11. 126
      elpha-ios/Base.lproj/Main.storyboard
  12. 16
      elpha-ios/ComposeAccessoryView.swift
  13. 20
      elpha-ios/ComposeViewController.swift
  14. 5
      elpha-ios/Elpha.xcdatamodeld/Elpha.xcdatamodel/contents
  15. 2
      elpha-ios/InstanceViewController.swift
  16. 2
      elpha-ios/InstancesDataManager.swift
  17. 2
      elpha-ios/InstancesTableViewController.swift
  18. 6
      elpha-ios/MastodonAPI.swift
  19. 10
      elpha-ios/SettingsTableViewController.swift
  20. 21
      elpha-ios/StatusTableViewController.swift
  21. 67
      elpha-ios/StatusView.swift
  22. 27
      elpha-ios/TimelineTableViewController.swift
  23. 10
      elpha-ios/TimelinesViewController.swift
  24. 8
      elpha-ios/VisibilityInputView.swift

22
elpha-ios/AbstractStatusTableViewController.swift

@ -16,7 +16,7 @@ protocol AbstractStatusTableViewCell {
class AbstractStatusTableViewController: UITableViewController, StatusViewDelegate {
let fetchLimit = 20
var fetchedResultsController: NSFetchedResultsController<StatusMO>? = nil
var fetchedResultsController: NSFetchedResultsController<StatusMO>?
var loading: Bool = false {
didSet {
@ -40,32 +40,32 @@ class AbstractStatusTableViewController: UITableViewController, StatusViewDelega
return UIStoryboard(name: "Main", bundle: nil)
}
func accountTapped(account: AccountMO) {
func accountTapped(_ sender: Any, account: AccountMO) {
if let controller = storyboard().instantiateViewController(withIdentifier: "AccountTableViewController") as? AccountTableViewController {
controller.account = account
self.navigationController?.pushViewController(controller, animated: true)
}
}
func statusTapped(status: StatusMO) {
func statusTapped(_ sender: Any, status: StatusMO) {
if let controller = storyboard().instantiateViewController(withIdentifier: "StatusTableViewController") as? StatusTableViewController {
controller.status = status
self.navigationController?.pushViewController(controller, animated: true)
}
}
func loadMoreTapped(status: StatusMO, direction: PaginationDirection) {
func loadMoreTapped(_ sender: Any, status: StatusMO, direction: PaginationDirection) {
}
func replyTapped(status: StatusMO) {
func replyTapped(_ sender: Any, status: StatusMO) {
if let controller = storyboard().instantiateViewController(withIdentifier: "ComposeViewController") as? ComposeViewController {
controller.replyToStatus = status
present(controller, animated: true)
}
}
func attachmentTapped(status: StatusMO, index: Int) {
func attachmentTapped(_ sender: Any, status: StatusMO, index: Int) {
if let controller = storyboard().instantiateViewController(withIdentifier: "AttachmentPageViewController") as? AttachmentPageViewController {
controller.status = status
controller.attachmentIndex = index
@ -74,7 +74,7 @@ class AbstractStatusTableViewController: UITableViewController, StatusViewDelega
}
}
func urlTapped(url: URL) {
func urlTapped(_ sender: Any, url: URL) {
let controller = SFSafariViewController(url: url)
controller.delegate = self
controller.dismissButtonStyle = .done
@ -83,10 +83,10 @@ class AbstractStatusTableViewController: UITableViewController, StatusViewDelega
present(controller, animated: true)
}
func revealTapped() {}
func hideTapped() {}
func boostTapped() {}
func favoriteTapped() {}
func revealTapped(_ sender: Any) {}
func hideTapped(_ sender: Any) {}
func boostTapped(_ sender: Any) {}
func favoriteTapped(_ sender: Any) {}
func updateCell(_ cell: AbstractStatusTableViewCell, withStatusAt indexPath: IndexPath) {
guard let status = fetchedResultsController?.object(at: indexPath) else {

35
elpha-ios/AccountTableViewController.swift

@ -12,7 +12,7 @@ import UIKit
import SafariServices
class FieldTableViewController: NSObject, UITableViewDelegate, UITableViewDataSource {
var fields: [AccountField]? = nil
var fields: [AccountField]?
func numberOfSections(in tableView: UITableView) -> Int {
return 1
@ -75,8 +75,8 @@ class AccountTableViewController: AbstractStatusTableViewController {
@IBOutlet var contentTextView: UITextViewFixed!
@IBOutlet var fieldTableView: UITableView!
var account: AccountMO? = nil
var fieldTableViewController: FieldTableViewController? = nil
var account: AccountMO?
var fieldTableViewController: FieldTableViewController?
override var currentPaginationContext: String {
get {
@ -90,6 +90,8 @@ class AccountTableViewController: AbstractStatusTableViewController {
@IBAction func statusTypeChanged(_ sender: UISegmentedControl) {
initializeFetchedResultsController()
tableView.reloadData()
fetch()
}
@ -110,7 +112,7 @@ class AccountTableViewController: AbstractStatusTableViewController {
if let account = account {
updateHeader(withAccount: account)
sizeHeaderToFit()
// sizeHeaderToFit()
initializeFetchedResultsController()
}
@ -137,18 +139,25 @@ class AccountTableViewController: AbstractStatusTableViewController {
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
sizeHeaderToFit()
}
private func sizeHeaderToFit() {
headerView.translatesAutoresizingMaskIntoConstraints = false
let headerWidth = headerView.bounds.size.width
let headerWidthConstraints = NSLayoutConstraint.constraints(withVisualFormat: "[headerView(width)]", options: NSLayoutConstraint.FormatOptions(rawValue: UInt(0)), metrics: ["width": headerWidth], views: ["headerView": headerView])
headerView.addConstraints(headerWidthConstraints)
headerView.setNeedsLayout()
headerView.layoutIfNeeded()
// var frame = headerView.frame
// frame.size.height = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize).height
// headerView.frame = frame
let headerSize = headerView.systemLayoutSizeFitting(UIView.layoutFittingCompressedSize)
let height = headerSize.height
var frame = headerView.frame
frame.size.height = height
headerView.frame = frame
headerView.removeConstraints(headerWidthConstraints)
headerView.translatesAutoresizingMaskIntoConstraints = true
}
private func updateHeader(withAccount account: AccountMO) {
@ -186,7 +195,7 @@ class AccountTableViewController: AbstractStatusTableViewController {
}
}
override func loadMoreTapped(status: StatusMO, direction: PaginationDirection) {
override func loadMoreTapped(_ sender: Any, status: StatusMO, direction: PaginationDirection) {
func removeMarker(at: Int) {
status.markers?.remove(at: at)
CoreDataManager.shared.saveContext()

4
elpha-ios/AlertManager.swift

@ -28,8 +28,8 @@ class AlertManager {
static let alertEndPosition: CGFloat = -80.0
var done: Bool = true
var alertView: AlertView? = nil
var bottomLayoutConstraint: NSLayoutConstraint? = nil
var alertView: AlertView?
var bottomLayoutConstraint: NSLayoutConstraint?
var alerts: [Alert] = []
func createAlertView() {

2
elpha-ios/AlertView.swift

@ -13,7 +13,7 @@ import UIKit
@IBOutlet var alertImageView: UIImageView!
@IBOutlet var alertLabel: UILabel!
var alert: Alert? = nil
var alert: Alert?
override init(frame: CGRect) {
super.init(frame: frame)

6
elpha-ios/AppDelegate.swift

@ -6,9 +6,13 @@
// Copyright © 2018 Elpha. All rights reserved.
//
import CoreData
import UIKit
extension Notification.Name {
static let didAuthenticate = Notification.Name("didAuthenticate")
static let didUnauthenticate = Notification.Name("didUnauthenticate")
}
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?

8
elpha-ios/AttachmentManager.swift

@ -9,16 +9,16 @@
import Kingfisher
import UIKit
protocol AttachmentManagerDelegate {
func attachmentTapped(index: Int)
protocol AttachmentManagerDelegate: class {
func attachmentTapped(_ sender: Any, index: Int)
}
class AttachmentManager: NSObject {
var delegate: AttachmentManagerDelegate? = nil
weak var delegate: AttachmentManagerDelegate?
@objc func attachmentTapped(_ gestureRecognizer: UITapGestureRecognizer) {
if let delegate = delegate, let name = gestureRecognizer.name {
delegate.attachmentTapped(index: Int(name)!)
delegate.attachmentTapped(self, index: Int(name)!)
}
}

2
elpha-ios/AttachmentPageViewController.swift

@ -9,7 +9,7 @@
import UIKit
class AttachmentPageViewController: UIPageViewController {
var status: StatusMO? = nil
var status: StatusMO?
var controllers: [UIViewController] = []
var attachmentIndex = 0

2
elpha-ios/AttachmentViewController.swift

@ -14,7 +14,7 @@ class AttachmentViewController: UIViewController {
@IBOutlet var attachmentImageView: UIImageView!
@IBOutlet var statusTextView: UITextView!
var attachment: AttachmentMO? = nil
var attachment: AttachmentMO?
@IBAction func closeTapped(_ sender: Any) {
if let controller = self.parent as? AttachmentPageViewController {

18
elpha-ios/AuthenticateViewController.swift

@ -24,14 +24,6 @@ class AuthenticateViewController: UIViewController {
instanceTextField.attributedPlaceholder = NSAttributedString(string: "mastodon.social", attributes: [NSAttributedString.Key.foregroundColor: UIColor.init(red: 0.9, green: 0.9, blue: 0.9, alpha: 1)])
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if AuthenticationManager.session != nil {
self.dismiss(animated: true)
}
}
override open var shouldAutorotate: Bool {
return false
}
@ -122,11 +114,15 @@ extension AuthenticateViewController: SFSafariViewControllerDelegate {
}
extension AuthenticateViewController: AuthenticationDelegate {
func authenticationSuccess() {
self.dismiss(animated: true)
func authenticationSuccess(_ sender: Any) {
NotificationCenter.default.post(name: .didAuthenticate, object: nil)
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.dismiss(animated: true)
}
}
func authenticationFailure(error: Error?) {
func authenticationFailure(_ sender: Any, error: Error?) {
AlertManager.shared.show(message: error?.localizedDescription ?? "Authentication error", category: .error)
}
}

34
elpha-ios/AuthenticationManager.swift

@ -10,15 +10,15 @@ import Alamofire
import CoreData
import UIKit
protocol AuthenticationDelegate {
func authenticationSuccess()
func authenticationFailure(error: Error?)
protocol AuthenticationDelegate: class {
func authenticationSuccess(_ sender: Any)
func authenticationFailure(_ sender: Any, error: Error?)
}
class AuthenticationManager {
static var authenticationState: String? = nil
static var authenticationClient: ClientMO? = nil
static var authenticationDelegate: AuthenticationDelegate? = nil
static var authenticationState: String?
static var authenticationClient: ClientMO?
static weak var authenticationDelegate: AuthenticationDelegate?
static var sessions: [SessionMO] {
get {
@ -75,6 +75,15 @@ class AuthenticationManager {
return session
}
static func deleteSelectedSession() {
guard let session = self.session else {
return
}
KeychainWrapper.standard.removeObject(forKey: "token:\(session.account!.username!)@\(session.client!.host!)")
CoreDataManager.shared.context.delete(session)
}
static func handle(url: URL) {
guard let state = authenticationState, let client = authenticationClient else {
return
@ -89,10 +98,7 @@ class AuthenticationManager {
code = item.value
case "state":
if item.value != state {
if let delegate = self.authenticationDelegate {
delegate.authenticationFailure(error: nil)
}
self.authenticationDelegate?.authenticationFailure(self, error: nil)
return
}
default:
@ -127,15 +133,11 @@ class AuthenticationManager {
let account = MastodonDataManager.upsertAccount(data)
_ = AuthenticationManager.saveSession(client: client, account: account!, token: token)
if let delegate = self.authenticationDelegate {
delegate.authenticationSuccess()
}
self.authenticationDelegate?.authenticationSuccess(self)
}
}
case .failure(let error):
if let delegate = self.authenticationDelegate {
delegate.authenticationFailure(error: error)
}
self.authenticationDelegate?.authenticationFailure(self, error: error)
}
}
}

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

@ -608,61 +608,85 @@
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="deT-ms-U3E">
<rect key="frame" x="0.0" y="254" width="375" height="188"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Note" textAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="7EZ-R5-qfQ" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="uXA-ni-Ikc">
<rect key="frame" x="0.0" y="0.0" width="375" height="76.333333333333329"/>
<subviews>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Note" textAlignment="center" translatesAutoresizingMaskIntoConstraints="NO" id="7EZ-R5-qfQ" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="8" y="8.0000000000000036" width="359" height="60.333333333333343"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Secondary"/>
<color key="textColor" name="Text"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<dataDetectorType key="dataDetectorTypes" phoneNumber="YES" link="YES" address="YES" calendarEvent="YES" shipmentTrackingNumber="YES" flightNumber="YES" lookupSuggestion="YES"/>
</textView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Secondary"/>
<color key="textColor" name="Text"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<dataDetectorType key="dataDetectorTypes" phoneNumber="YES" link="YES" address="YES" calendarEvent="YES" shipmentTrackingNumber="YES" flightNumber="YES" lookupSuggestion="YES"/>
</textView>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="40" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="LkG-MC-taI">
<constraints>
<constraint firstItem="7EZ-R5-qfQ" firstAttribute="leading" secondItem="uXA-ni-Ikc" secondAttribute="leading" constant="8" id="0TG-kr-cxx"/>
<constraint firstItem="7EZ-R5-qfQ" firstAttribute="top" secondItem="uXA-ni-Ikc" secondAttribute="top" constant="8" id="2UQ-wc-G6z"/>
<constraint firstAttribute="trailing" secondItem="7EZ-R5-qfQ" secondAttribute="trailing" constant="8" id="6bB-Ym-g2Z"/>
<constraint firstAttribute="bottom" secondItem="7EZ-R5-qfQ" secondAttribute="bottom" constant="8" id="Uvm-mv-9mm"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="qdo-DJ-E9W">
<rect key="frame" x="0.0" y="76.333333333333314" width="375" height="111.66666666666669"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="separatorInset" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationWidth="0.0" reuseIdentifier="FieldTableViewCell" rowHeight="40" id="Yja-kQ-VB8" customClass="FieldTableViewCell" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="40"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Yja-kQ-VB8" id="c3e-LW-md8">
<rect key="frame" x="0.0" y="0.0" width="375" height="39.666666666666664"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mB7-gb-eAr">
<rect key="frame" x="23.000000000000004" y="12" width="35.333333333333343" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" name="Secondary"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="Value" textAlignment="right" translatesAutoresizingMaskIntoConstraints="NO" id="C63-Uw-F1z" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="68.333333333333343" y="11" width="281.66666666666663" height="18"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Primary"/>
<subviews>
<tableView clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" scrollEnabled="NO" dataMode="prototypes" style="plain" separatorStyle="default" allowsSelection="NO" rowHeight="40" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="LkG-MC-taI">
<rect key="frame" x="0.0" y="0.0" width="375" height="111.66666666666667"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<inset key="separatorInset" minX="5" minY="0.0" maxX="0.0" maxY="0.0"/>
<prototypes>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" selectionStyle="none" hidesAccessoryWhenEditing="NO" indentationWidth="0.0" reuseIdentifier="FieldTableViewCell" rowHeight="40" id="Yja-kQ-VB8" customClass="FieldTableViewCell" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="40"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Yja-kQ-VB8" id="c3e-LW-md8">
<rect key="frame" x="0.0" y="0.0" width="375" height="39.666666666666664"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mB7-gb-eAr">
<rect key="frame" x="16.000000000000004" y="12" width="35.333333333333343" height="16"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" name="Secondary"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="Value" textAlignment="right" translatesAutoresizingMaskIntoConstraints="NO" id="C63-Uw-F1z" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="61.333333333333343" y="11" width="295.66666666666663" height="18"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Primary"/>
<constraints>
<constraint firstAttribute="height" constant="18" id="83I-iT-Ly1"/>
</constraints>
<color key="textColor" name="Text"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
</subviews>
<constraints>
<constraint firstAttribute="height" constant="18" id="83I-iT-Ly1"/>
<constraint firstAttribute="trailingMargin" secondItem="C63-Uw-F1z" secondAttribute="trailing" constant="10" id="Cyo-5b-bjd"/>
<constraint firstItem="mB7-gb-eAr" firstAttribute="centerY" secondItem="c3e-LW-md8" secondAttribute="centerY" id="ERo-WH-lvG"/>
<constraint firstItem="C63-Uw-F1z" firstAttribute="centerY" secondItem="c3e-LW-md8" secondAttribute="centerY" id="Lf3-kd-1Ly"/>
<constraint firstItem="C63-Uw-F1z" firstAttribute="leading" secondItem="mB7-gb-eAr" secondAttribute="trailing" constant="10" id="Lwt-bU-uYO"/>
<constraint firstItem="mB7-gb-eAr" firstAttribute="leading" secondItem="c3e-LW-md8" secondAttribute="leadingMargin" constant="8" id="Mvh-Ku-V7L"/>
</constraints>
<color key="textColor" name="Text"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
<textInputTraits key="textInputTraits" autocorrectionType="no" spellCheckingType="no" smartDashesType="no" smartInsertDeleteType="no" smartQuotesType="no"/>
<dataDetectorType key="dataDetectorTypes" link="YES"/>
</textView>
</subviews>
<constraints>
<constraint firstAttribute="trailingMargin" secondItem="C63-Uw-F1z" secondAttribute="trailing" constant="10" id="Cyo-5b-bjd"/>
<constraint firstItem="mB7-gb-eAr" firstAttribute="centerY" secondItem="c3e-LW-md8" secondAttribute="centerY" id="ERo-WH-lvG"/>
<constraint firstItem="C63-Uw-F1z" firstAttribute="centerY" secondItem="c3e-LW-md8" secondAttribute="centerY" id="Lf3-kd-1Ly"/>
<constraint firstItem="C63-Uw-F1z" firstAttribute="leading" secondItem="mB7-gb-eAr" secondAttribute="trailing" constant="10" id="Lwt-bU-uYO"/>
<constraint firstItem="mB7-gb-eAr" firstAttribute="leading" secondItem="c3e-LW-md8" secondAttribute="leadingMargin" constant="8" id="Mvh-Ku-V7L"/>
</constraints>
</tableViewCellContentView>
<connections>
<outlet property="nameLabel" destination="mB7-gb-eAr" id="WSF-Wm-EDv"/>
<outlet property="valueTextView" destination="C63-Uw-F1z" id="ebT-QB-lYN"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</tableViewCellContentView>
<connections>
<outlet property="nameLabel" destination="mB7-gb-eAr" id="WSF-Wm-EDv"/>
<outlet property="valueTextView" destination="C63-Uw-F1z" id="ebT-QB-lYN"/>
</connections>
</tableViewCell>
</prototypes>
</tableView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="LkG-MC-taI" firstAttribute="top" secondItem="qdo-DJ-E9W" secondAttribute="top" id="1Pz-cl-JIT"/>
<constraint firstAttribute="trailing" secondItem="LkG-MC-taI" secondAttribute="trailing" id="IML-bL-0vl"/>
<constraint firstItem="LkG-MC-taI" firstAttribute="leading" secondItem="qdo-DJ-E9W" secondAttribute="leading" id="KxB-zP-7k6"/>
<constraint firstAttribute="bottom" secondItem="LkG-MC-taI" secondAttribute="bottom" id="OyV-y7-iIs"/>
</constraints>
</view>
</subviews>
</stackView>
</subviews>
@ -961,7 +985,7 @@
<rect key="frame" x="0.0" y="0.0" width="375" height="43.666666666666664"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Clear Data Store" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K77-zb-cI5">
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Sign Out" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="K77-zb-cI5">
<rect key="frame" x="16" y="14" width="343" height="15.666666666666664"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" red="1" green="0.14913141730000001" blue="0.0" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>

16
elpha-ios/ComposeAccessoryView.swift

@ -8,10 +8,10 @@
import UIKit
protocol ComposeAccessoryViewDelegate {
func attachmentTapped()
func visibilityTapped()
func tootTapped()
protocol ComposeAccessoryViewDelegate: class {
func attachmentTapped(_ sender: Any)
func visibilityTapped(_ sender: Any)
func tootTapped(_ sender: Any)
}
class ComposeAccessoryView: UIView {
@ -20,7 +20,7 @@ class ComposeAccessoryView: UIView {
@IBOutlet var visibilityButton: UIButton!
@IBOutlet var tootButton: UIButton!
var delegate: ComposeAccessoryViewDelegate? = nil
weak var delegate: ComposeAccessoryViewDelegate?
var selectedVisibility: StatusVisibility = .public {
didSet {
@ -50,14 +50,14 @@ class ComposeAccessoryView: UIView {
}
@objc func attachmentTapped() {
delegate?.attachmentTapped()
delegate?.attachmentTapped(self)
}
@objc func visibilityTapped() {
delegate?.visibilityTapped()
delegate?.visibilityTapped(self)
}
@objc func tootTapped() {
delegate?.tootTapped()
delegate?.tootTapped(self)
}
}

20
elpha-ios/ComposeViewController.swift

@ -22,13 +22,13 @@ class ComposeViewController: UIViewController {
let characterLimit = 500
let composeAccessoryViewHeight: CGFloat = 55.0
var feedbackGenerator: UINotificationFeedbackGenerator? = nil
var replyToStatus: StatusMO? = nil
var composeAccessoryView: ComposeAccessoryView? = nil
var feedbackGenerator: UINotificationFeedbackGenerator?
var replyToStatus: StatusMO?
var composeAccessoryView: ComposeAccessoryView?
var selectedVisibility: StatusVisibility = .public
var attachmentInputView: AttachmentInputView? = nil
var visibilityInputView: VisibilityInputView? = nil
var attachmentInputView: AttachmentInputView?
var visibilityInputView: VisibilityInputView?
override func viewDidLoad() {
super.viewDidLoad()
@ -109,17 +109,17 @@ extension ComposeViewController: UITextViewDelegate {
}
extension ComposeViewController: ComposeAccessoryViewDelegate, VisibilityInputViewDelegate {
func attachmentTapped() {
func attachmentTapped(_ sender: Any) {
statusTextView.inputView = statusTextView.inputView == nil ? attachmentInputView : nil
statusTextView.reloadInputViews()
}
func visibilityTapped() {
func visibilityTapped(_ sender: Any) {
statusTextView.inputView = statusTextView.inputView == nil ? visibilityInputView : nil
statusTextView.reloadInputViews()
}
func tootTapped() {
func tootTapped(_ sender: Any) {
if let content = statusTextView.text {
if !content.isEmpty && content.count <= characterLimit {
feedbackGenerator?.prepare()
@ -132,7 +132,7 @@ extension ComposeViewController: ComposeAccessoryViewDelegate, VisibilityInputVi
}
self.feedbackGenerator?.notificationOccurred(.success)
AlertManager.shared.show(message: "Toot!", category: .normal)
AlertManager.shared.show(message: "Toot!", category: .toot)
self.statusTextView.text = ""
self.contentWarningTextField.text = ""
@ -142,7 +142,7 @@ extension ComposeViewController: ComposeAccessoryViewDelegate, VisibilityInputVi
}
}
func visibilitySelected(visibility: StatusVisibility) {
func visibilitySelected(_ sender: Any, visibility: StatusVisibility) {
selectedVisibility = visibility
composeAccessoryView?.selectedVisibility = visibility

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

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14315.18" systemVersion="18A391" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<model type="com.apple.IDECoreDataModeler.DataModel" documentVersion="1.0" lastSavedToolsVersion="14460.32" systemVersion="18B75" minimumToolsVersion="Automatic" sourceLanguage="Swift" userDefinedModelVersionIdentifier="">
<entity name="Account" representedClassName="AccountMO" syncable="YES" codeGenerationType="class">
<attribute name="acct" attributeType="String" syncable="YES"/>
<attribute name="avatarStaticURL" optional="YES" attributeType="URI" syncable="YES"/>
@ -134,6 +134,9 @@
<relationship name="reblogs" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="reblog" inverseEntity="Status" syncable="YES"/>
<relationship name="tags" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Tag" inverseName="statuses" inverseEntity="Tag" syncable="YES"/>
<relationship name="timelines" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Timeline" inverseName="statuses" inverseEntity="Timeline" syncable="YES"/>
<fetchIndex name="createdAtIndex">
<fetchIndexElement property="createdAt" type="Binary" order="descending"/>
</fetchIndex>
</entity>
<entity name="Tag" representedClassName="TagMO" syncable="YES" codeGenerationType="class">
<attribute name="name" attributeType="String" syncable="YES"/>

2
elpha-ios/InstanceViewController.swift

@ -19,7 +19,7 @@ class InstanceViewController: UIViewController {
@IBOutlet var connectionsLabel: UILabel!
@IBOutlet var uptimeLabel: UILabel!
var instance: ISInstanceMO? = nil
var instance: ISInstanceMO?
override var previewActionItems: [UIPreviewActionItem] {
let action = UIPreviewAction(title: "Go to website", style: .default) { action, viewController in

2
elpha-ios/InstancesDataManager.swift

@ -15,7 +15,7 @@ class InstancesDataManager {
let fetchLimit = 20
var instances: [ISInstanceMO] = []
var nextID: String? = nil
var nextID: String?
var finished = false
func upsertLanguage(string: String) -> ISLanguageMO? {

2
elpha-ios/InstancesTableViewController.swift

@ -15,7 +15,7 @@ class InstancesTableViewController: UITableViewController {
@IBOutlet var mainNavigationItem: UINavigationItem!
let fetchLimit = 20
var fetchedResultsController: NSFetchedResultsController<ISInstanceMO>? = nil
var fetchedResultsController: NSFetchedResultsController<ISInstanceMO>?
var loading: Bool = false {
didSet {

6
elpha-ios/MastodonAPI.swift

@ -392,9 +392,8 @@ class MastodonAPI {
}
static func search(content: String, completion: @escaping (JSONObject?, Error?) -> Void) {
let parameters: Parameters = [
"q": content
]
let parameters: Parameters = ["q": content]
self.request(path: "api/v2/search", method: .get, parameters: parameters) { data, _, error in
guard error == nil else {
completion(nil, error)
@ -405,7 +404,6 @@ class MastodonAPI {
}
}
static func registerApp(serverURL: URL, completion: @escaping (JSONObject?, Error?) -> Void) {
let requestURL = serverURL.appendingPathComponent("api/v1/apps")
let parameters: Parameters = [

10
elpha-ios/SettingsTableViewController.swift

@ -47,9 +47,7 @@ class SettingsTableViewController: UITableViewController {
self.parent?.present(controller, animated: true)
}
case 3:
let alert = UIAlertController(title: "Not Implemented", message: "Clear Data Store not implemented yet.", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "OK", style: .default))
self.parent?.present(alert, animated: true)
unauthenticate()
default:
return
}
@ -62,4 +60,10 @@ class SettingsTableViewController: UITableViewController {
@IBAction func refreshTimelinesChanged(_ sender: Any) {
SettingsManager.automaticallyRefreshTimelines = refreshTimelinesSwitch.isOn
}
func unauthenticate() {
AuthenticationManager.deleteSelectedSession()
NotificationCenter.default.post(name: .didUnauthenticate, object: nil)
self.dismiss(animated: true)
}
}

21
elpha-ios/StatusTableViewController.swift

@ -12,8 +12,8 @@ import UIKit
import SafariServices
class StatusTableViewController: AbstractStatusTableViewController, UIGestureRecognizerDelegate {
public var status: StatusMO? = nil
var feedbackGenerator: UINotificationFeedbackGenerator? = nil
public var status: StatusMO?
var feedbackGenerator: UINotificationFeedbackGenerator?
override func viewDidLoad() {
super.viewDidLoad()
@ -24,7 +24,6 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
refreshControl?.addTarget(self, action: #selector(self.fetch), for: .valueChanged)
initializeFetchedResultsController()
scrollToMainStatusRow()
self.fetch()
}
@ -49,10 +48,10 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
}
@IBAction func accountViewTapped(_ sender: Any) {
self.accountTapped(account: status!.account!)
self.accountTapped(self, account: status!.account!)
}
@IBAction func boostTapped(_ sender: Any) {
@IBAction func boostTapped(_ sender: UIView) {
if let status = status {
feedbackGenerator?.prepare()
@ -90,7 +89,7 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
}
}
@IBAction func favoriteTapped(_ sender: Any) {
@IBAction func favoriteTapped(_ sender: UIView) {
if let status = status {
feedbackGenerator?.prepare()
@ -129,7 +128,7 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
}
@IBAction func replyTapped(_ sender: Any) {
self.replyTapped(status: status!)
self.replyTapped(self, status: status!)
}
@IBAction func shareTapped(_ sender: Any) {
@ -392,8 +391,8 @@ extension StatusTableViewController {
}
extension StatusTableViewController: AttachmentManagerDelegate {
func attachmentTapped(index: Int) {
self.attachmentTapped(status: status!, index: index)
func attachmentTapped(_ sender: Any, index: Int) {
self.attachmentTapped(self, status: status!, index: index)
}
}
@ -403,7 +402,7 @@ extension StatusTableViewController: UITextViewDelegate {
for mention in mentions {
if URL == mention.url {
if let account = MastodonDataManager.account(id: mention.id) {
self.accountTapped(account: account)
self.accountTapped(self, account: account)
}
return false
@ -412,7 +411,7 @@ extension StatusTableViewController: UITextViewDelegate {
}
if URL.scheme == "http" || URL.scheme == "https" {
self.urlTapped(url: URL)
self.urlTapped(self, url: URL)
}
return false

67
elpha-ios/StatusView.swift

@ -9,17 +9,17 @@
import Kingfisher
import UIKit
protocol StatusViewDelegate {
func accountTapped(account: AccountMO)
func statusTapped(status: StatusMO)
func loadMoreTapped(status: StatusMO, direction: PaginationDirection)
func attachmentTapped(status: StatusMO, index: Int)
func urlTapped(url: URL)
func boostTapped()
func favoriteTapped()
func replyTapped(status: StatusMO)
func revealTapped()
func hideTapped()
protocol StatusViewDelegate: class {
func accountTapped(_ sender: Any, account: AccountMO)
func statusTapped(_ sender: Any, status: StatusMO)
func loadMoreTapped(_ sender: Any, status: StatusMO, direction: PaginationDirection)
func attachmentTapped(_ sender: Any, status: StatusMO, index: Int)
func urlTapped(_ sender: Any, url: URL)
func boostTapped(_ sender: Any)
func favoriteTapped(_ sender: Any)
func replyTapped(_ sender: Any, status: StatusMO)
func revealTapped(_ sender: Any)
func hideTapped(_ sender: Any)
}
class StatusView: UIView {
@ -52,15 +52,16 @@ class StatusView: UIView {
@IBOutlet var bottomLoadMoreView: UIView!
@IBOutlet var contentTextView: UITextView!
var status: StatusMO? = nil
var delegate: StatusViewDelegate? = nil
var spoilerView: UIVisualEffectView? = nil
var status: StatusMO?
var spoilerView: UIVisualEffectView?
var feedbackGenerator: UINotificationFeedbackGenerator?
var attachmentManager: AttachmentManager = AttachmentManager()
var feedbackGenerator: UINotificationFeedbackGenerator? = nil
weak var delegate: StatusViewDelegate?
@IBAction func boostViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.accountTapped(account: status.account!)
delegate.accountTapped(self, account: status.account!)
}
}
@ -69,16 +70,16 @@ class StatusView: UIView {
let status = status,
let replyAccountID = status.inReplyToAccountID,
let replyAccount = MastodonDataManager.account(id: replyAccountID) {
delegate.accountTapped(account: replyAccount)
delegate.accountTapped(self, account: replyAccount)
}
}
@IBAction func accountViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
if let reblog = status.reblog {
delegate.accountTapped(account: reblog.account!)
delegate.accountTapped(self, account: reblog.account!)
} else {
delegate.accountTapped(account: status.account!)
delegate.accountTapped(self, account: status.account!)
}
}
}
@ -86,9 +87,9 @@ class StatusView: UIView {
@IBAction func mainViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
if let reblog = status.reblog {
delegate.statusTapped(status: reblog)
delegate.statusTapped(self, status: reblog)
} else {
delegate.statusTapped(status: status)
delegate.statusTapped(self, status: status)
}
}
}
@ -97,19 +98,19 @@ class StatusView: UIView {
if let status = status {
status.hidden = true
CoreDataManager.shared.saveContext()
delegate?.hideTapped()
delegate?.hideTapped(self)
}
}
@IBAction func topLoadMoreViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.loadMoreTapped(status: status, direction: .prev)
delegate.loadMoreTapped(self, status: status, direction: .prev)
}
}
@IBAction func bottomLoadMoreViewTapped(_ sender: Any) {
if let delegate = delegate, let status = status {
delegate.loadMoreTapped(status: status, direction: .next)
delegate.loadMoreTapped(self, status: status, direction: .next)
}
}
@ -155,7 +156,7 @@ class StatusView: UIView {
}
CoreDataManager.shared.saveContext()
delegate?.boostTapped()
delegate?.boostTapped(self)
}
}
@ -194,19 +195,19 @@ class StatusView: UIView {
}
CoreDataManager.shared.saveContext()
delegate?.favoriteTapped()
delegate?.favoriteTapped(self)
}
}
@IBAction func replyTapped(_ sender: Any) {
delegate?.replyTapped(status: status!)
delegate?.replyTapped(self, status: status!)
}
@objc func reveal(sender: UITapGestureRecognizer) {
if let status = status {
status.hidden = false
CoreDataManager.shared.saveContext()
delegate?.revealTapped()
delegate?.revealTapped(self)
}
}
@ -369,12 +370,12 @@ class StatusView: UIView {
}
extension StatusView: AttachmentManagerDelegate {
func attachmentTapped(index: Int) {
func attachmentTapped(_ sender: Any, index: Int) {
if let delegate = delegate, let status = status {
if let reblog = status.reblog {
delegate.attachmentTapped(status: reblog, index: index)
delegate.attachmentTapped(self, status: reblog, index: index)
} else {
delegate.attachmentTapped(status: status, index: index)
delegate.attachmentTapped(self, status: status, index: index)
}
}
}
@ -386,7 +387,7 @@ extension StatusView: UITextViewDelegate {
for mention in mentions {
if URL == mention.url {
if let account = MastodonDataManager.account(id: mention.id) {
delegate?.accountTapped(account: account)
delegate?.accountTapped(self, account: account)
}
return false
@ -395,7 +396,7 @@ extension StatusView: UITextViewDelegate {
}
if URL.scheme == "http" || URL.scheme == "https" {
delegate?.urlTapped(url: URL)
delegate?.urlTapped(self, url: URL)
}
return false

27
elpha-ios/TimelineTableViewController.swift

@ -12,7 +12,7 @@ import UIKit
import SafariServices
class TimelineTableViewController: AbstractStatusTableViewController {
var feedbackGenerator: UINotificationFeedbackGenerator? = nil
var feedbackGenerator: UINotificationFeedbackGenerator?
override var currentPaginationContext: String {
get {
@ -78,21 +78,20 @@ class TimelineTableViewController: AbstractStatusTableViewController {
}
refreshControl?.addTarget(self, action: #selector(self.fetch), for: .valueChanged)
NotificationCenter.default.addObserver(self, selector: #selector(onDidAuthenticate), name: .didAuthenticate, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(onDidUnauthenticate), name: .didUnauthenticate, object: nil)
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if fetchedResultsController?.fetchedObjects?.count ?? 0 == 0 {
initializeFetchedResultsController()
}
if SettingsManager.automaticallyRefreshTimelines {
self.fetch()
fetch()
}
}
override func loadMoreTapped(status: StatusMO, direction: PaginationDirection) {
override func loadMoreTapped(_ sender: Any, status: StatusMO, direction: PaginationDirection) {
func removeMarker(at: Int) {
status.markers?.remove(at: at)
CoreDataManager.shared.saveContext()
@ -133,6 +132,16 @@ class TimelineTableViewController: AbstractStatusTableViewController {
}
}
@objc func onDidAuthenticate(_ notification: Notification) {
initializeFetchedResultsController()
tableView.reloadData()
fetch()
}
@objc func onDidUnauthenticate(_ notification: Notification) {
performSegue(withIdentifier: "AuthenticateSegue", sender: self)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "TimelinesSegue" {
if let destination = segue.destination as? TimelinesViewController {
@ -389,7 +398,7 @@ extension TimelineTableViewController {
}
extension TimelineTableViewController: TimelinesViewControllerDelegate {
func didSelect(timeline: TimelineMO) {
func didSelect(_ sender: Any, timeline: TimelineMO) {
navigationItem.title = timeline.name
AuthenticationManager.session?.timeline = timeline
CoreDataManager.shared.saveContext()
@ -398,7 +407,7 @@ extension TimelineTableViewController: TimelinesViewControllerDelegate {
tableView.reloadData()
if SettingsManager.automaticallyRefreshTimelines {
self.fetch()
fetch()
}
}
}

10
elpha-ios/TimelinesViewController.swift

@ -9,15 +9,15 @@
import CoreData
import UIKit
protocol TimelinesViewControllerDelegate {
func didSelect(timeline: TimelineMO)
protocol TimelinesViewControllerDelegate: class {
func didSelect(_ sender: Any, timeline: TimelineMO)
}
class TimelinesViewController: UIViewController {
@IBOutlet var tableView: UITableView!
var delegate: TimelinesViewControllerDelegate? = nil
var fetchedResultsController: NSFetchedResultsController<TimelineMO>? = nil
weak var delegate: TimelinesViewControllerDelegate?
var fetchedResultsController: NSFetchedResultsController<TimelineMO>?
override func viewDidLoad() {
super.viewDidLoad()
@ -130,7 +130,7 @@ extension TimelinesViewController: UITableViewDataSource, UITableViewDelegate {
}
if let delegate = self.delegate {
delegate.didSelect(timeline: timeline)
delegate.didSelect(self, timeline: timeline)
}
dismiss(animated: true)

8
elpha-ios/VisibilityInputView.swift

@ -8,15 +8,15 @@
import UIKit
protocol VisibilityInputViewDelegate {
func visibilitySelected(visibility: StatusVisibility)
protocol VisibilityInputViewDelegate: class {
func visibilitySelected(_ sender: Any, visibility: StatusVisibility)
}
class VisibilityInputView: UIView {
@IBOutlet var contentView: UIView!
@IBOutlet var visibilityPickerView: UIPickerView!
public var delegate: VisibilityInputViewDelegate? = nil
public weak var delegate: VisibilityInputViewDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
@ -53,6 +53,6 @@ extension VisibilityInputView: UIPickerViewDelegate, UIPickerViewDataSource {
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
delegate?.visibilitySelected(visibility: StatusVisibility.allCases[row])
delegate?.visibilitySelected(self, visibility: StatusVisibility.allCases[row])
}
}
Loading…
Cancel
Save