forked from shadowfacts/Tusker
parent
e04cdd16d6
commit
d5887f1f02
|
@ -56,6 +56,7 @@ extension Notification {
|
|||
case follow
|
||||
case followRequest = "follow_request"
|
||||
case poll
|
||||
case update
|
||||
case unknown
|
||||
}
|
||||
}
|
||||
|
|
|
@ -46,6 +46,8 @@
|
|||
D61DC84D28F500D200B82C6E /* ProfileViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61DC84C28F500D200B82C6E /* ProfileViewController.swift */; };
|
||||
D61F75882932DB6000C0B37F /* StatusSwipeAction.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75872932DB6000C0B37F /* StatusSwipeAction.swift */; };
|
||||
D61F758A2932E1FC00C0B37F /* SwipeActionsPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F75892932E1FC00C0B37F /* SwipeActionsPrefsView.swift */; };
|
||||
D61F758D2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D61F758B2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift */; };
|
||||
D61F758E2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = D61F758C2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.xib */; };
|
||||
D620483423D3801D008A63EF /* LinkTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483323D3801D008A63EF /* LinkTextView.swift */; };
|
||||
D620483623D38075008A63EF /* ContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483523D38075008A63EF /* ContentTextView.swift */; };
|
||||
D620483823D38190008A63EF /* StatusContentTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D620483723D38190008A63EF /* StatusContentTextView.swift */; };
|
||||
|
@ -410,6 +412,8 @@
|
|||
D61DC84C28F500D200B82C6E /* ProfileViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProfileViewController.swift; sourceTree = "<group>"; };
|
||||
D61F75872932DB6000C0B37F /* StatusSwipeAction.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusSwipeAction.swift; sourceTree = "<group>"; };
|
||||
D61F75892932E1FC00C0B37F /* SwipeActionsPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SwipeActionsPrefsView.swift; sourceTree = "<group>"; };
|
||||
D61F758B2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusUpdatedNotificationTableViewCell.swift; sourceTree = "<group>"; };
|
||||
D61F758C2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = StatusUpdatedNotificationTableViewCell.xib; sourceTree = "<group>"; };
|
||||
D620483323D3801D008A63EF /* LinkTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkTextView.swift; sourceTree = "<group>"; };
|
||||
D620483523D38075008A63EF /* ContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentTextView.swift; sourceTree = "<group>"; };
|
||||
D620483723D38190008A63EF /* StatusContentTextView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusContentTextView.swift; sourceTree = "<group>"; };
|
||||
|
@ -1086,6 +1090,8 @@
|
|||
D64BC18E23C18B9D000D0238 /* FollowRequestNotificationTableViewCell.xib */,
|
||||
D662AEED263A3B880082A153 /* PollFinishedTableViewCell.swift */,
|
||||
D662AEEE263A3B880082A153 /* PollFinishedTableViewCell.xib */,
|
||||
D61F758B2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift */,
|
||||
D61F758C2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.xib */,
|
||||
);
|
||||
path = Notifications;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1704,6 +1710,7 @@
|
|||
D667E5E12134937B0057A976 /* TimelineStatusTableViewCell.xib in Resources */,
|
||||
D6F2E966249E8BFD005846BB /* IssueReporterViewController.xib in Resources */,
|
||||
D662AEF0263A3B880082A153 /* PollFinishedTableViewCell.xib in Resources */,
|
||||
D61F758E2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.xib in Resources */,
|
||||
D6A4DCCD2553667800D9DE31 /* FastAccountSwitcherViewController.xib in Resources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
|
@ -1980,6 +1987,7 @@
|
|||
D6262C9A28D01C4B00390C1F /* LoadingTableViewCell.swift in Sources */,
|
||||
D68C2AE325869BAB00548EFF /* AuxiliarySceneDelegate.swift in Sources */,
|
||||
D66C900B28DAB7FD00217BF2 /* TimelineViewController.swift in Sources */,
|
||||
D61F758D2933C69C00C0B37F /* StatusUpdatedNotificationTableViewCell.swift in Sources */,
|
||||
D6AEBB432321685E00E5038B /* OpenInSafariActivity.swift in Sources */,
|
||||
D6C693FE2162FEEA007D6A6D /* UIViewController+Children.swift in Sources */,
|
||||
D61A45EA28DF51EE002BE511 /* TimelineLikeCollectionViewController.swift in Sources */,
|
||||
|
|
|
@ -16,6 +16,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
|||
private let followGroupCell = "followGroupCell"
|
||||
private let followRequestCell = "followRequestCell"
|
||||
private let pollCell = "pollCell"
|
||||
private let updatedCell = "updatedCell"
|
||||
private let unknownCell = "unknownCell"
|
||||
|
||||
weak var mastodonController: MastodonController!
|
||||
|
@ -51,6 +52,7 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
|||
tableView.register(UINib(nibName: "FollowNotificationGroupTableViewCell", bundle: .main), forCellReuseIdentifier: followGroupCell)
|
||||
tableView.register(UINib(nibName: "FollowRequestNotificationTableViewCell", bundle: .main), forCellReuseIdentifier: followRequestCell)
|
||||
tableView.register(UINib(nibName: "PollFinishedTableViewCell", bundle: .main), forCellReuseIdentifier: pollCell)
|
||||
tableView.register(UINib(nibName: "StatusUpdatedNotificationTableViewCell", bundle: .main), forCellReuseIdentifier: updatedCell)
|
||||
tableView.register(UINib(nibName: "BasicTableViewCell", bundle: .main), forCellReuseIdentifier: unknownCell)
|
||||
}
|
||||
|
||||
|
@ -98,6 +100,13 @@ class NotificationsTableViewController: DiffableTimelineLikeTableViewController<
|
|||
cell.updateUI(notification: notification)
|
||||
return cell
|
||||
|
||||
case .update:
|
||||
guard let notification = group.notifications.first,
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: updatedCell, for: indexPath) as? StatusUpdatedNotificationTableViewCell else { fatalError() }
|
||||
cell.delegate = self
|
||||
cell.updateUI(notification: notification)
|
||||
return cell
|
||||
|
||||
case .unknown:
|
||||
let cell = tableView.dequeueReusableCell(withIdentifier: unknownCell, for: indexPath)
|
||||
cell.textLabel!.text = NSLocalizedString("Unknown Notification", comment: "unknown notification fallback cell text")
|
||||
|
|
|
@ -52,7 +52,7 @@ class PollFinishedTableViewCell: UITableViewCell {
|
|||
displayNameLabel.text = notification.account.displayName
|
||||
displayNameLabel.setEmojis(notification.account.emojis, identifier: notification.account.id)
|
||||
|
||||
let doc = try! SwiftSoup.parse(status.content)
|
||||
let doc = try! SwiftSoup.parseBodyFragment(status.content)
|
||||
statusContentLabel.text = try! doc.text()
|
||||
|
||||
pollView.updateUI(status: status, poll: poll)
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
//
|
||||
// StatusUpdatedNotificationTableViewCell.swift
|
||||
// Tusker
|
||||
//
|
||||
// Created by Shadowfacts on 11/27/22.
|
||||
// Copyright © 2022 Shadowfacts. All rights reserved.
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Pachyderm
|
||||
import SwiftSoup
|
||||
|
||||
class StatusUpdatedNotificationTableViewCell: UITableViewCell {
|
||||
|
||||
weak var delegate: (TuskerNavigationDelegate & MenuActionProvider)?
|
||||
|
||||
@IBOutlet weak var timestampLabel: UILabel!
|
||||
@IBOutlet weak var displayNameLabel: EmojiLabel!
|
||||
@IBOutlet weak var contentLabel: UILabel!
|
||||
|
||||
private var notification: Pachyderm.Notification?
|
||||
private var updateTimestampWorkItem: DispatchWorkItem?
|
||||
|
||||
override func awakeFromNib() {
|
||||
super.awakeFromNib()
|
||||
|
||||
timestampLabel.font = UIFont(descriptor: .preferredFontDescriptor(withTextStyle: .body).addingAttributes([
|
||||
.traits: [
|
||||
UIFontDescriptor.TraitKey.weight: UIFont.Weight.light.rawValue,
|
||||
]
|
||||
]), size: 0)
|
||||
timestampLabel.adjustsFontForContentSizeCategory = true
|
||||
|
||||
displayNameLabel.font = .preferredFont(forTextStyle: .body).withTraits(.traitBold)!
|
||||
displayNameLabel.adjustsFontForContentSizeCategory = true
|
||||
}
|
||||
|
||||
func updateUI(notification: Pachyderm.Notification) {
|
||||
guard notification.kind == .update,
|
||||
let status = notification.status else {
|
||||
return
|
||||
}
|
||||
|
||||
self.notification = notification
|
||||
|
||||
updateTimestamp()
|
||||
|
||||
displayNameLabel.text = notification.account.displayName
|
||||
displayNameLabel.setEmojis(notification.account.emojis, identifier: notification.account.id)
|
||||
|
||||
let doc = try! SwiftSoup.parseBodyFragment(status.content)
|
||||
contentLabel.text = try! doc.text()
|
||||
}
|
||||
|
||||
private func updateTimestamp() {
|
||||
guard let 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 StatusUpdatedNotificationTableViewCell: SelectableTableViewCell {
|
||||
func didSelectCell() {
|
||||
guard let delegate,
|
||||
let status = notification?.status else {
|
||||
return
|
||||
}
|
||||
let vc = delegate.conversation(mainStatusID: status.id, state: .unknown)
|
||||
delegate.show(vc)
|
||||
}
|
||||
}
|
||||
|
||||
extension StatusUpdatedNotificationTableViewCell: MenuPreviewProvider {
|
||||
func getPreviewProviders(for location: CGPoint, sourceViewController: UIViewController) -> PreviewProviders? {
|
||||
guard let 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: {
|
||||
delegate.actionsForStatus(status, sourceView: self)
|
||||
})
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21507" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
|
||||
<device id="retina6_12" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21505"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="System colors in document resources" minToolsVersion="11.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
</dependencies>
|
||||
<objects>
|
||||
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
|
||||
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
|
||||
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" rowHeight="124" id="KGk-i7-Jjw" customClass="StatusUpdatedNotificationTableViewCell" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="124"/>
|
||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="KGk-i7-Jjw" id="H2p-sc-9uM">
|
||||
<rect key="frame" x="0.0" y="0.0" width="320" height="124"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="ZWN-ni-RLP">
|
||||
<rect key="frame" x="74" y="11" width="230" height="102"/>
|
||||
<subviews>
|
||||
<stackView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="HLB-Iv-HTR">
|
||||
<rect key="frame" x="0.0" y="0.0" width="230" height="20.333333333333332"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="A post was edited" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="mBx-jm-6sU">
|
||||
<rect key="frame" x="0.0" y="0.0" width="206" height="20.333333333333332"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<nil key="textColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="252" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="2m" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="04d-Lt-yL5">
|
||||
<rect key="frame" x="206" y="0.0" width="24" height="20.333333333333332"/>
|
||||
<fontDescription key="fontDescription" type="system" weight="light" pointSize="17"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" verticalHuggingPriority="251" horizontalCompressionResistancePriority="751" text="Person" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="F5w-FN-c33" customClass="EmojiLabel" customModule="Tusker" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="24.333333333333336" width="230" height="20.333333333333336"/>
|
||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="17"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" text="Content" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontForContentSizeCategory="YES" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A4y-Se-5rW">
|
||||
<rect key="frame" x="0.0" y="48.666666666666657" width="230" height="53.333333333333343"/>
|
||||
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
|
||||
<color key="textColor" systemColor="secondaryLabelColor"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
</subviews>
|
||||
</stackView>
|
||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="pencil" catalog="system" translatesAutoresizingMaskIntoConstraints="NO" id="3pZ-j9-PPP">
|
||||
<rect key="frame" x="36" y="11" width="30" height="31"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="30" id="FOx-Ib-CH7"/>
|
||||
<constraint firstAttribute="height" constant="30" id="UNQ-xp-O8B"/>
|
||||
</constraints>
|
||||
<preferredSymbolConfiguration key="preferredSymbolConfiguration" scale="large"/>
|
||||
</imageView>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="3pZ-j9-PPP" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="6Aw-t0-5vM"/>
|
||||
<constraint firstItem="ZWN-ni-RLP" firstAttribute="top" secondItem="H2p-sc-9uM" secondAttribute="topMargin" id="88f-jC-7Dk"/>
|
||||
<constraint firstItem="ZWN-ni-RLP" firstAttribute="leading" secondItem="3pZ-j9-PPP" secondAttribute="trailing" constant="8" id="R68-9I-Bnh"/>
|
||||
<constraint firstAttribute="bottomMargin" secondItem="ZWN-ni-RLP" secondAttribute="bottom" id="eCm-M2-qlS"/>
|
||||
<constraint firstItem="ZWN-ni-RLP" firstAttribute="leading" secondItem="H2p-sc-9uM" secondAttribute="leadingMargin" constant="58" id="r84-Xe-N1F"/>
|
||||
<constraint firstAttribute="trailingMargin" secondItem="ZWN-ni-RLP" secondAttribute="trailing" id="w0X-u7-BPp"/>
|
||||
</constraints>
|
||||
</tableViewCellContentView>
|
||||
<viewLayoutGuide key="safeArea" id="njF-e1-oar"/>
|
||||
<connections>
|
||||
<outlet property="contentLabel" destination="A4y-Se-5rW" id="1j0-QT-bzy"/>
|
||||
<outlet property="displayNameLabel" destination="F5w-FN-c33" id="q3K-Od-YxV"/>
|
||||
<outlet property="timestampLabel" destination="04d-Lt-yL5" id="VeH-73-9Gh"/>
|
||||
</connections>
|
||||
<point key="canvasLocation" x="74.809160305343511" y="16.901408450704228"/>
|
||||
</tableViewCell>
|
||||
</objects>
|
||||
<resources>
|
||||
<image name="pencil" catalog="system" width="128" height="113"/>
|
||||
<systemColor name="secondaryLabelColor">
|
||||
<color red="0.23529411764705882" green="0.23529411764705882" blue="0.2627450980392157" alpha="0.59999999999999998" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</systemColor>
|
||||
</resources>
|
||||
</document>
|
Loading…
Reference in New Issue