Browse Source

Add Tooting

master
Dwayne Harris 6 years ago
parent
commit
e1f5bc79b2
  1. 55
      elpha-ios/Base.lproj/Main.storyboard
  2. 29
      elpha-ios/ComposeViewController.swift
  3. 4
      elpha-ios/FLAnimatedImageView+LoadImageURL.swift
  4. 31
      elpha-ios/MastodonAPI.swift
  5. 41
      elpha-ios/StatusTableViewController.swift
  6. 20
      elpha-ios/StatusView.swift
  7. 4
      elpha-ios/TimelineTableViewController.swift

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

@ -1066,44 +1066,44 @@
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="TaE-kM-jSH">
<rect key="frame" x="0.0" y="80" width="375" height="698"/>
<rect key="frame" x="0.0" y="70" width="375" height="708"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="yeC-3y-hAG">
<rect key="frame" x="0.0" y="0.0" width="375" height="698"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="708"/>
<subviews>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="w3S-pT-NYF">
<rect key="frame" x="0.0" y="0.0" width="375" height="180"/>
<rect key="frame" x="0.0" y="0.0" width="375" height="160"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Replying To" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="co5-cA-nTI">
<rect key="frame" x="20" y="8" width="335" height="30"/>
<constraints>
<constraint firstAttribute="height" constant="30" id="YlZ-hK-ikz"/>
</constraints>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="16"/>
<color key="textColor" name="Primary"/>
<nil key="highlightedColor"/>
</label>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="DBM-gJ-bmW" customClass="FLAnimatedImageView">
<rect key="frame" x="20" y="53" width="45" height="45"/>
<rect key="frame" x="20" y="48" width="40" height="40"/>
<constraints>
<constraint firstAttribute="height" constant="45" id="Odb-PW-C0m"/>
<constraint firstAttribute="width" constant="45" id="eJR-OK-tSg"/>
<constraint firstAttribute="height" constant="40" id="Odb-PW-C0m"/>
<constraint firstAttribute="width" constant="40" id="eJR-OK-tSg"/>
</constraints>
</imageView>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Display Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="htY-mN-l6s">
<rect key="frame" x="73" y="53" width="282" height="20.333333333333329"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
<rect key="frame" x="68" y="48" width="287" height="18"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="15"/>
<color key="textColor" name="Text"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Username" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="P5v-hq-2Ee">
<rect key="frame" x="73" y="75.333333333333343" width="282" height="18"/>
<fontDescription key="fontDescription" type="system" pointSize="15"/>
<rect key="frame" x="68" y="68" width="287" height="15.666666666666671"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" name="Primary"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Content" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="wi5-07-ou8" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="20" y="113" width="335" height="59"/>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" editable="NO" text="Content" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="wi5-07-ou8" customClass="UITextViewFixed" customModule="elpha_ios" customModuleProvider="target">
<rect key="frame" x="20" y="98" width="335" height="54"/>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Primary"/>
<color key="textColor" name="Text"/>
@ -1115,28 +1115,28 @@
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstItem="P5v-hq-2Ee" firstAttribute="top" secondItem="htY-mN-l6s" secondAttribute="bottom" constant="2" id="3cF-2A-z1a"/>
<constraint firstItem="htY-mN-l6s" firstAttribute="top" secondItem="co5-cA-nTI" secondAttribute="bottom" constant="15" id="5q8-gy-TNz"/>
<constraint firstItem="htY-mN-l6s" firstAttribute="top" secondItem="co5-cA-nTI" secondAttribute="bottom" constant="10" id="5q8-gy-TNz"/>
<constraint firstItem="co5-cA-nTI" firstAttribute="leading" secondItem="w3S-pT-NYF" secondAttribute="leading" constant="20" id="AcU-cS-MkN"/>
<constraint firstItem="htY-mN-l6s" firstAttribute="leading" secondItem="DBM-gJ-bmW" secondAttribute="trailing" constant="8" id="BoK-Jc-mUZ"/>
<constraint firstAttribute="trailing" secondItem="wi5-07-ou8" secondAttribute="trailing" constant="20" id="LH6-kW-CnZ"/>
<constraint firstAttribute="bottom" secondItem="wi5-07-ou8" secondAttribute="bottom" constant="8" id="V6M-9G-xOh"/>
<constraint firstAttribute="trailing" secondItem="P5v-hq-2Ee" secondAttribute="trailing" constant="20" id="W4Q-IT-0Oe"/>
<constraint firstItem="wi5-07-ou8" firstAttribute="top" secondItem="DBM-gJ-bmW" secondAttribute="bottom" constant="15" id="Wad-bN-IVn"/>
<constraint firstItem="wi5-07-ou8" firstAttribute="top" secondItem="DBM-gJ-bmW" secondAttribute="bottom" constant="10" id="Wad-bN-IVn"/>
<constraint firstItem="wi5-07-ou8" firstAttribute="leading" secondItem="w3S-pT-NYF" secondAttribute="leading" constant="20" id="YlR-MT-7L7"/>
<constraint firstItem="DBM-gJ-bmW" firstAttribute="top" secondItem="co5-cA-nTI" secondAttribute="bottom" constant="15" id="gJf-bQ-lJH"/>
<constraint firstItem="DBM-gJ-bmW" firstAttribute="top" secondItem="co5-cA-nTI" secondAttribute="bottom" constant="10" id="gJf-bQ-lJH"/>
<constraint firstItem="P5v-hq-2Ee" firstAttribute="leading" secondItem="DBM-gJ-bmW" secondAttribute="trailing" constant="8" id="gqO-Uc-pq3"/>
<constraint firstItem="co5-cA-nTI" firstAttribute="top" secondItem="w3S-pT-NYF" secondAttribute="top" constant="8" id="qIa-AE-nyn"/>
<constraint firstAttribute="trailing" secondItem="htY-mN-l6s" secondAttribute="trailing" constant="20" id="s3Z-Vx-dco"/>
<constraint firstAttribute="trailing" secondItem="co5-cA-nTI" secondAttribute="trailing" constant="20" id="sCf-x8-mNG"/>
<constraint firstItem="DBM-gJ-bmW" firstAttribute="leading" secondItem="w3S-pT-NYF" secondAttribute="leading" constant="20" id="tFt-Ki-sef"/>
<constraint firstAttribute="height" constant="180" id="zVv-ls-E8L"/>
<constraint firstAttribute="height" constant="160" id="zVv-ls-E8L"/>
</constraints>
</view>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="LeJ-qN-f3j">
<rect key="frame" x="0.0" y="180" width="375" height="518"/>
<rect key="frame" x="0.0" y="160" width="375" height="548"/>
<subviews>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Content Warning" textAlignment="natural" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="D8y-nm-aIL">
<rect key="frame" x="20" y="409.33333333333337" width="335" height="35"/>
<rect key="frame" x="20" y="439.33333333333337" width="335" height="35"/>
<constraints>
<constraint firstAttribute="height" constant="35" id="Pja-qP-5Hb"/>
</constraints>
@ -1145,7 +1145,7 @@
<textInputTraits key="textInputTraits"/>
</textField>
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="kek-uj-Dhl">
<rect key="frame" x="20" y="361.33333333333337" width="335" height="40"/>
<rect key="frame" x="20" y="391.33333333333337" width="335" height="40"/>
<subviews>
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ClN-BL-Y5Y">
<rect key="frame" x="0.0" y="5" width="80" height="30"/>
@ -1165,6 +1165,9 @@
<state key="normal" title=" Toot">
<color key="titleColor" name="Primary"/>
</state>
<connections>
<action selector="tootTapped:" destination="MNp-Rq-Swn" eventType="touchUpInside" id="2p7-22-rrO"/>
</connections>
</button>
</subviews>
<constraints>
@ -1178,19 +1181,19 @@
</constraints>
</view>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="500" textAlignment="right" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="lj5-34-gkN">
<rect key="frame" x="20" y="336.33333333333337" width="335" height="17"/>
<rect key="frame" x="20" y="366.33333333333337" width="335" height="17"/>
<fontDescription key="fontDescription" type="system" pointSize="14"/>
<color key="textColor" name="Primary"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Description of content warnings." lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="L6c-Q0-xOK">
<rect key="frame" x="20" y="452.33333333333337" width="335" height="15.666666666666686"/>
<rect key="frame" x="20" y="482.33333333333337" width="335" height="15.666666666666686"/>
<fontDescription key="fontDescription" type="system" pointSize="13"/>
<color key="textColor" cocoaTouchSystemColor="scrollViewTexturedBackgroundColor"/>
<nil key="highlightedColor"/>
</label>
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="9BJ-55-1nh">
<rect key="frame" x="20" y="8" width="335" height="320.33333333333331"/>
<rect key="frame" x="20" y="8" width="335" height="350.33333333333331"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<color key="tintColor" name="Primary"/>
<color key="textColor" name="Text"/>
@ -1233,7 +1236,7 @@
</constraints>
</scrollView>
<imageView contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="Close" translatesAutoresizingMaskIntoConstraints="NO" id="7bB-Lp-9yL">
<rect key="frame" x="20" y="54" width="18" height="18"/>
<rect key="frame" x="20" y="44" width="18" height="18"/>
<gestureRecognizers/>
<constraints>
<constraint firstAttribute="height" constant="18" id="aZg-Zz-VMv"/>
@ -1248,13 +1251,13 @@
<constraints>
<constraint firstItem="TaE-kM-jSH" firstAttribute="leading" secondItem="s1W-PY-h1k" secondAttribute="leading" id="E9Q-ZS-xWL"/>
<constraint firstItem="7bB-Lp-9yL" firstAttribute="leading" secondItem="s1W-PY-h1k" secondAttribute="leading" constant="20" id="Ouq-rl-JgK"/>
<constraint firstItem="TaE-kM-jSH" firstAttribute="top" secondItem="s1W-PY-h1k" secondAttribute="top" constant="80" id="Xyy-bK-L6U"/>
<constraint firstItem="TaE-kM-jSH" firstAttribute="top" secondItem="s1W-PY-h1k" secondAttribute="top" constant="70" id="Xyy-bK-L6U"/>
<constraint firstAttribute="trailing" secondItem="TaE-kM-jSH" secondAttribute="trailing" id="u7p-wI-aDf"/>
<constraint firstAttribute="bottom" secondItem="TaE-kM-jSH" secondAttribute="bottom" id="uV9-Tt-dTp"/>
<constraint firstItem="TaE-kM-jSH" firstAttribute="top" secondItem="7bB-Lp-9yL" secondAttribute="bottom" constant="8" id="v75-Uk-r4i"/>
</constraints>
</view>
<blurEffect style="light"/>
<blurEffect style="extraLight"/>
</visualEffectView>
</subviews>
<color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>

29
elpha-ios/ComposeViewController.swift

@ -21,11 +21,15 @@ class ComposeViewController: UIViewController {
@IBOutlet var tootButton: UIButton!
@IBOutlet var bottomConstraint: NSLayoutConstraint!
let characterLimit = 500
var feedbackGenerator: UINotificationFeedbackGenerator? = nil
var replyToStatus: StatusMO? = nil
override func viewDidLoad() {
super.viewDidLoad()
feedbackGenerator = UINotificationFeedbackGenerator()
replyToAvatarImageView.layer.cornerRadius = 10
replyToAvatarImageView.layer.masksToBounds = true
@ -84,11 +88,34 @@ class ComposeViewController: UIViewController {
@IBAction func dismissTapped(_ sender: Any) {
dismiss(animated: true)
}
@IBAction func tootTapped(_ sender: Any) {
if let content = statusTextView.text {
if !content.isEmpty && content.count <= characterLimit {
feedbackGenerator?.prepare()
MastodonAPI.postStatus(content: content, replyToID: replyToStatus?.id, spoilerText: contentWarningTextField.text) { error in
guard error == nil else {
self.feedbackGenerator?.notificationOccurred(.error)
AlertManager.shared.show(message: "Couldn't toot!", category: .error)
return
}
self.feedbackGenerator?.notificationOccurred(.success)
AlertManager.shared.show(message: "Toot!")
self.statusTextView.text = ""
self.contentWarningTextField.text = ""
self.dismiss(animated: true)
}
}
}
}
}
extension ComposeViewController: UITextViewDelegate {
func textViewDidChange(_ textView: UITextView) {
let characters = statusTextView.text!.count
statusCharacterCountLabel.text = String(500 - characters)
statusCharacterCountLabel.text = String(characterLimit - characters)
}
}

4
elpha-ios/FLAnimatedImageView+LoadImageURL.swift

@ -49,7 +49,7 @@ extension FLAnimatedImageView {
self.image = UIImage(named: "Help")
}
func loadImageURL(_ url: URL) {
func loadImageURL(_ url: URL, contentMode: UIView.ContentMode = .scaleAspectFit) {
if let data = ImageCache.get(url: url) {
if url.absoluteString.hasSuffix(".gif") {
self.animatedImage = FLAnimatedImage(animatedGIFData: data)
@ -63,7 +63,7 @@ extension FLAnimatedImageView {
if let data = response.data {
DispatchQueue.main.async {
ImageCache.set(url: url, data: data)
self.contentMode = .scaleAspectFill
self.contentMode = contentMode
if url.absoluteString.hasSuffix(".gif") {
self.animatedImage = FLAnimatedImage(animatedGIFData: data)

31
elpha-ios/MastodonAPI.swift

@ -14,8 +14,7 @@ typealias JSONArray = [Any]
typealias JSONObjectArray = [JSONObject]
enum MastodonRequestError: Error {
case noResponse
case unauthenticated
case noResponse, unauthenticated
}
enum TimelineCategory: String {
@ -26,6 +25,10 @@ enum PaginationDirection: String {
case prev, next
}
enum StatusVisibility: String {
case direct, `private`, unlisted, `public`
}
public class PaginationItem: NSObject, NSCoding {
let direction: PaginationDirection
let statusID: String
@ -360,6 +363,30 @@ class MastodonAPI {
}
}
static func postStatus(content: String, replyToID: String?, spoilerText: String?, visibility: StatusVisibility = .public, completion: @escaping (Error?) -> Void) {
var parameters: Parameters = [
"status": content,
"visibility": visibility.rawValue,
]
if let replyToID = replyToID {
parameters["in_reply_to_id"] = replyToID
}
if let spoilerText = spoilerText {
parameters["spoiler_text"] = spoilerText
}
self.request(path: "api/v1/statuses", method: .post, parameters: parameters) { _, _, error in
guard error == nil else {
completion(error)
return
}
completion(nil)
}
}
static func registerApp(serverURL: URL, completion: @escaping (JSONObject?, Error?) -> Void) {
let requestURL = serverURL.appendingPathComponent("api/v1/apps")
let parameters: Parameters = [

41
elpha-ios/StatusTableViewController.swift

@ -46,7 +46,7 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
@IBAction func boostTapped(_ sender: Any) {
if let status = status {
feedbackGenerator!.prepare()
feedbackGenerator?.prepare()
if status.reblogged {
status.reblogged = false
@ -55,12 +55,12 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
MastodonAPI.unreblog(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Unboosted", category: .boosted)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
} else {
status.reblogged = true
@ -69,12 +69,12 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
MastodonAPI.reblog(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Boosted!", category: .boosted)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
}
@ -84,7 +84,7 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
@IBAction func favoriteTapped(_ sender: Any) {
if let status = status {
feedbackGenerator!.prepare()
feedbackGenerator?.prepare()
if status.favorited {
status.favorited = false
@ -93,12 +93,12 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
MastodonAPI.unfavorite(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Unfavorited", category: .favorited)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
} else {
status.favorited = true
@ -107,12 +107,12 @@ class StatusTableViewController: AbstractStatusTableViewController, UIGestureRec
MastodonAPI.favorite(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Favorited!", category: .favorited)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
}
@ -262,6 +262,8 @@ extension StatusTableViewController {
fatalError("Unable to find reusable cell")
}
cell.contentTextView.delegate = self
cell.avatarImageView.layer.shadowColor = UIColor.black.cgColor
cell.avatarImageView.layer.shadowOpacity = 0.8
cell.avatarImageView.layer.shadowOffset = CGSize.zero
@ -368,3 +370,22 @@ extension StatusTableViewController: AttachmentManagerDelegate {
self.attachmentTapped(status: status!, index: index)
}
}
extension StatusTableViewController: UITextViewDelegate {
func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
if let mentions = status?.mentions {
for mention in mentions {
if URL == mention.url {
if let account = MastodonDataManager.account(id: mention.id) {
self.accountTapped(account: account)
}
return false
}
}
}
self.urlTapped(url: URL)
return false
}
}

20
elpha-ios/StatusView.swift

@ -125,7 +125,7 @@ class StatusView: UIView {
@IBAction func boostTapped(_ sender: Any) {
if let status = status {
feedbackGenerator!.prepare()
feedbackGenerator?.prepare()
if status.reblogged {
status.reblogged = false
@ -134,12 +134,12 @@ class StatusView: UIView {
MastodonAPI.unreblog(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Unboosted", category: .boosted)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
} else {
status.reblogged = true
@ -148,12 +148,12 @@ class StatusView: UIView {
MastodonAPI.reblog(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Boosted!", category: .boosted)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
}
@ -164,7 +164,7 @@ class StatusView: UIView {
@IBAction func favoriteTapped(_ sender: Any) {
if let status = status {
feedbackGenerator!.prepare()
feedbackGenerator?.prepare()
if status.favorited {
status.favorited = false
@ -173,12 +173,12 @@ class StatusView: UIView {
MastodonAPI.unfavorite(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Unfavorited", category: .favorited)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
} else {
status.favorited = true
@ -187,12 +187,12 @@ class StatusView: UIView {
MastodonAPI.favorite(statusID: status.id!) { error in
guard error == nil else {
AlertManager.shared.show(message: error!.localizedDescription, category: .error)
self.feedbackGenerator!.notificationOccurred(.error)
self.feedbackGenerator?.notificationOccurred(.error)
return
}
AlertManager.shared.show(message: "Favorited!", category: .favorited)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
}

4
elpha-ios/TimelineTableViewController.swift

@ -199,7 +199,7 @@ class TimelineTableViewController: AbstractStatusTableViewController {
DispatchQueue.main.async {
var newStatusCount = 0
self.feedbackGenerator!.prepare()
self.feedbackGenerator?.prepare()
for (index, status) in data.enumerated() {
if let upsertResult = MastodonDataManager.upsertStatus(status) {
@ -239,7 +239,7 @@ class TimelineTableViewController: AbstractStatusTableViewController {
if newStatusCount > 0 {
let pluralization = newStatusCount == 1 ? "" : "s"
AlertManager.shared.show(message: "\(newStatusCount) new toot\(pluralization)", category: .newStatuses)
self.feedbackGenerator!.notificationOccurred(.success)
self.feedbackGenerator?.notificationOccurred(.success)
}
CoreDataManager.shared.saveContext()

Loading…
Cancel
Save