diff --git a/Pachyderm/Model/Notification.swift b/Pachyderm/Model/Notification.swift index fadb3758..84ca0025 100644 --- a/Pachyderm/Model/Notification.swift +++ b/Pachyderm/Model/Notification.swift @@ -55,6 +55,7 @@ extension Notification { case favourite case follow case followRequest = "follow_request" + case poll case unknown } } diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index df765cd1..fbbb13e1 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -158,6 +158,8 @@ D65C6BF525478A9C00A6E89C /* BackgroundableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65C6BF425478A9C00A6E89C /* BackgroundableViewController.swift */; }; D65F613423AEAB6600F3CFD3 /* OnboardingTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = D65F613323AEAB6600F3CFD3 /* OnboardingTests.swift */; }; D6620ACE2511A0ED00312CA0 /* StatusStateResolver.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6620ACD2511A0ED00312CA0 /* StatusStateResolver.swift */; }; + D662AEEF263A3B880082A153 /* PollFinishedTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D662AEED263A3B880082A153 /* PollFinishedTableViewCell.swift */; }; + D662AEF0263A3B880082A153 /* PollFinishedTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D662AEEE263A3B880082A153 /* PollFinishedTableViewCell.xib */; }; D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */; }; D663625F2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */; }; D663626221360B1900C9CBA2 /* Preferences.swift in Sources */ = {isa = PBXBuildFile; fileRef = D663626121360B1900C9CBA2 /* Preferences.swift */; }; @@ -217,7 +219,6 @@ D69693FA25859A8000F4E116 /* ComposeSceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D69693F925859A8000F4E116 /* ComposeSceneDelegate.swift */; }; D6969E9E240C81B9002843CE /* NSTextAttachment+Emoji.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6969E9D240C81B9002843CE /* NSTextAttachment+Emoji.swift */; }; D6969EA0240C8384002843CE /* EmojiLabel.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6969E9F240C8384002843CE /* EmojiLabel.swift */; }; - D6969EA4240DD28D002843CE /* UnknownNotificationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D6969EA2240DD28D002843CE /* UnknownNotificationTableViewCell.xib */; }; D69CCBBF249E6EFD000AF167 /* CrashReporter in Frameworks */ = {isa = PBXBuildFile; productRef = D69CCBBE249E6EFD000AF167 /* CrashReporter */; }; D6A00B1D26379FC900316AD4 /* PollOptionsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A00B1C26379FC900316AD4 /* PollOptionsView.swift */; }; D6A3BC7723218E1300FD64D5 /* TimelineSegment.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6A3BC7323218C6E00FD64D5 /* TimelineSegment.swift */; }; @@ -535,6 +536,8 @@ D65F613523AFD65900F3CFD3 /* Ambassador.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Ambassador.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D65F613723AFD65D00F3CFD3 /* Embassy.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = Embassy.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D6620ACD2511A0ED00312CA0 /* StatusStateResolver.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusStateResolver.swift; sourceTree = ""; }; + D662AEED263A3B880082A153 /* PollFinishedTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollFinishedTableViewCell.swift; sourceTree = ""; }; + D662AEEE263A3B880082A153 /* PollFinishedTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = PollFinishedTableViewCell.xib; sourceTree = ""; }; D663625C2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = ConversationMainStatusTableViewCell.xib; sourceTree = ""; }; D663625E2135C75500C9CBA2 /* ConversationMainStatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ConversationMainStatusTableViewCell.swift; sourceTree = ""; }; D663626121360B1900C9CBA2 /* Preferences.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Preferences.swift; sourceTree = ""; }; @@ -594,7 +597,6 @@ D69693F925859A8000F4E116 /* ComposeSceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeSceneDelegate.swift; sourceTree = ""; }; D6969E9D240C81B9002843CE /* NSTextAttachment+Emoji.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "NSTextAttachment+Emoji.swift"; sourceTree = ""; }; D6969E9F240C8384002843CE /* EmojiLabel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EmojiLabel.swift; sourceTree = ""; }; - D6969EA2240DD28D002843CE /* UnknownNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = UnknownNotificationTableViewCell.xib; sourceTree = ""; }; D6A00B1C26379FC900316AD4 /* PollOptionsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollOptionsView.swift; sourceTree = ""; }; D6A3BC7323218C6E00FD64D5 /* TimelineSegment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineSegment.swift; sourceTree = ""; }; D6A3BC7823218E9200FD64D5 /* NotificationGroup.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationGroup.swift; sourceTree = ""; }; @@ -1185,7 +1187,8 @@ D6A3BC7F2321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib */, D64BC18D23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.swift */, D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */, - D6969EA2240DD28D002843CE /* UnknownNotificationTableViewCell.xib */, + D662AEED263A3B880082A153 /* PollFinishedTableViewCell.swift */, + D662AEEE263A3B880082A153 /* PollFinishedTableViewCell.xib */, ); path = Notifications; sourceTree = ""; @@ -1792,7 +1795,6 @@ D6D4DDD7212518A200E1C4BB /* Assets.xcassets in Resources */, D663625D2135C74800C9CBA2 /* ConversationMainStatusTableViewCell.xib in Resources */, D640D76922BAF5E6004FBE69 /* DomainBlocks.plist in Resources */, - D6969EA4240DD28D002843CE /* UnknownNotificationTableViewCell.xib in Resources */, D6289E84217B795D0003D1D7 /* LargeImageViewController.xib in Resources */, D6093FB125BE0B01004811E6 /* TrendingHashtagTableViewCell.xib in Resources */, D627FF79217E950100CC0648 /* DraftsTableViewController.xib in Resources */, @@ -1803,6 +1805,7 @@ D6A3BC812321B7E600FD64D5 /* FollowNotificationGroupTableViewCell.xib in Resources */, D667E5E12134937B0057A976 /* TimelineStatusTableViewCell.xib in Resources */, D6F2E966249E8BFD005846BB /* CrashReporterViewController.xib in Resources */, + D662AEF0263A3B880082A153 /* PollFinishedTableViewCell.xib in Resources */, D6A4DCCD2553667800D9DE31 /* FastAccountSwitcherViewController.xib in Resources */, ); runOnlyForDeploymentPostprocessing = 0; @@ -1920,6 +1923,7 @@ D600613E25D07E170067FAD6 /* ProfileDirectoryFilterView.swift in Sources */, D6DD353D22F28CD000A9563A /* ContentWarningCopyMode.swift in Sources */, 0427033A22B31269000D31B6 /* AdvancedPrefsView.swift in Sources */, + D662AEEF263A3B880082A153 /* PollFinishedTableViewCell.swift in Sources */, D626493C23C1000300612E6E /* AlbumTableViewCell.swift in Sources */, D62275A624F1C81800B82A16 /* ComposeReplyView.swift in Sources */, D60E2F292442372B005F8713 /* AccountMO.swift in Sources */, diff --git a/Tusker/Screens/Notifications/NotificationsTableViewController.swift b/Tusker/Screens/Notifications/NotificationsTableViewController.swift index cf7f69f5..24e67261 100644 --- a/Tusker/Screens/Notifications/NotificationsTableViewController.swift +++ b/Tusker/Screens/Notifications/NotificationsTableViewController.swift @@ -15,6 +15,7 @@ class NotificationsTableViewController: TimelineLikeTableViewController - + - - + diff --git a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.xib b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.xib index be1f165d..bc58578b 100644 --- a/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.xib +++ b/Tusker/Views/Notifications/FollowRequestNotificationTableViewCell.xib @@ -1,9 +1,8 @@ - + - - + diff --git a/Tusker/Views/Notifications/PollFinishedTableViewCell.swift b/Tusker/Views/Notifications/PollFinishedTableViewCell.swift new file mode 100644 index 00000000..e3c78ab5 --- /dev/null +++ b/Tusker/Views/Notifications/PollFinishedTableViewCell.swift @@ -0,0 +1,108 @@ +// +// PollFinishedTableViewCell.swift +// Tusker +// +// Created by Shadowfacts on 4/28/21. +// Copyright © 2021 Shadowfacts. All rights reserved. +// + +import UIKit +import Pachyderm +import SwiftSoup + +class PollFinishedTableViewCell: UITableViewCell { + + weak var delegate: TuskerNavigationDelegate? + var mastodonController: MastodonController? { delegate?.apiController } + + @IBOutlet weak var displayNameLabel: EmojiLabel! + @IBOutlet weak var timestampLabel: UILabel! + @IBOutlet weak var statusContentLabel: UILabel! + @IBOutlet weak var pollView: StatusPollView! + + var notification: Pachyderm.Notification? + + private var updateTimestampWorkItem: DispatchWorkItem? + + func updateUI(notification: Pachyderm.Notification) { + guard let statusID = notification.status?.id, + let status = delegate?.apiController.persistentContainer.status(for: statusID), + let poll = status.poll else { + return + } + + self.notification = notification + + updateTimestamp() + + displayNameLabel.text = notification.account.displayName + displayNameLabel.setEmojis(notification.account.emojis, identifier: notification.account.id) + + let doc = try! SwiftSoup.parse(status.content) + statusContentLabel.text = try! doc.text() + + pollView.updateUI(status: status, poll: poll) + } + + private func updateTimestamp() { + guard let notification = notification else { return } + + timestampLabel.text = notification.createdAt.timeAgoString() + + let delay: DispatchTimeInterval? + switch notification.createdAt.timeAgo().1 { + case .second: + delay = .seconds(10) + case .minute: + delay = .seconds(60) + default: + delay = nil + } + if let delay = delay { + if updateTimestampWorkItem == nil { + updateTimestampWorkItem = DispatchWorkItem { [weak self] in + self?.updateTimestamp() + } + DispatchQueue.main.asyncAfter(deadline: .now() + delay, execute: updateTimestampWorkItem!) + } + } else { + updateTimestampWorkItem = nil + } + } + + override func prepareForReuse() { + super.prepareForReuse() + + updateTimestampWorkItem?.cancel() + updateTimestampWorkItem = nil + } + +} + +extension PollFinishedTableViewCell: SelectableTableViewCell { + func didSelectCell() { + guard let delegate = delegate, + let status = notification?.status else { + return + } + let vc = delegate.conversation(mainStatusID: status.id, state: .unknown) + delegate.show(vc) + } +} + +extension PollFinishedTableViewCell: MenuPreviewProvider { + var navigationDelegate: TuskerNavigationDelegate? { delegate } + + func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? { + guard let delegate = delegate, + let statusID = notification?.status?.id, + let status = delegate.apiController.persistentContainer.status(for: statusID) else { + return nil + } + return (content: { + delegate.conversation(mainStatusID: statusID, state: .unknown) + }, actions: { + self.actionsForStatus(status, sourceView: self) + }) + } +} diff --git a/Tusker/Views/Notifications/PollFinishedTableViewCell.xib b/Tusker/Views/Notifications/PollFinishedTableViewCell.xib new file mode 100644 index 00000000..3ec33c60 --- /dev/null +++ b/Tusker/Views/Notifications/PollFinishedTableViewCell.xib @@ -0,0 +1,95 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Tusker/Views/Notifications/UnknownNotificationTableViewCell.xib b/Tusker/Views/Notifications/UnknownNotificationTableViewCell.xib deleted file mode 100644 index 8f226368..00000000 --- a/Tusker/Views/Notifications/UnknownNotificationTableViewCell.xib +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/Tusker/Views/Poll/PollOptionView.swift b/Tusker/Views/Poll/PollOptionView.swift index ed2b9118..6d851fd2 100644 --- a/Tusker/Views/Poll/PollOptionView.swift +++ b/Tusker/Views/Poll/PollOptionView.swift @@ -45,7 +45,7 @@ class PollOptionView: UIView { NSLayoutConstraint.activate([ fillView.leadingAnchor.constraint(equalTo: leadingAnchor), - fillView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: CGFloat(optionVotes) / CGFloat(poll.votesCount)), + fillView.widthAnchor.constraint(equalTo: widthAnchor, multiplier: poll.votesCount == 0 ? 0 : CGFloat(optionVotes) / CGFloat(poll.votesCount)), fillView.topAnchor.constraint(equalTo: topAnchor), fillView.bottomAnchor.constraint(equalTo: bottomAnchor), ])