chore: code format
This commit is contained in:
parent
ecf622b866
commit
ca7eb7bb12
|
@ -70,8 +70,9 @@
|
||||||
<attribute name="domain" attributeType="String"/>
|
<attribute name="domain" attributeType="String"/>
|
||||||
<attribute name="id" attributeType="String"/>
|
<attribute name="id" attributeType="String"/>
|
||||||
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
|
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
|
||||||
<attribute name="type" attributeType="String"/>
|
<attribute name="typeRaw" attributeType="String"/>
|
||||||
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
<attribute name="updatedAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||||
|
<attribute name="userID" attributeType="String"/>
|
||||||
<relationship name="account" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser"/>
|
<relationship name="account" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser"/>
|
||||||
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status"/>
|
<relationship name="status" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Status"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
|
@ -223,7 +224,7 @@
|
||||||
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
|
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
|
||||||
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
|
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
|
||||||
<element name="MastodonAuthentication" positionX="0" positionY="0" width="128" height="209"/>
|
<element name="MastodonAuthentication" positionX="0" positionY="0" width="128" height="209"/>
|
||||||
<element name="MastodonNotification" positionX="9" positionY="162" width="128" height="149"/>
|
<element name="MastodonNotification" positionX="9" positionY="162" width="128" height="164"/>
|
||||||
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="659"/>
|
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="659"/>
|
||||||
<element name="Mention" positionX="0" positionY="0" width="128" height="134"/>
|
<element name="Mention" positionX="0" positionY="0" width="128" height="134"/>
|
||||||
<element name="Poll" positionX="0" positionY="0" width="128" height="194"/>
|
<element name="Poll" positionX="0" positionY="0" width="128" height="194"/>
|
||||||
|
|
|
@ -12,13 +12,14 @@ public final class MastodonNotification: NSManagedObject {
|
||||||
public typealias ID = UUID
|
public typealias ID = UUID
|
||||||
@NSManaged public private(set) var identifier: ID
|
@NSManaged public private(set) var identifier: ID
|
||||||
@NSManaged public private(set) var id: String
|
@NSManaged public private(set) var id: String
|
||||||
@NSManaged public private(set) var domain: String
|
|
||||||
@NSManaged public private(set) var createAt: Date
|
@NSManaged public private(set) var createAt: Date
|
||||||
@NSManaged public private(set) var updatedAt: Date
|
@NSManaged public private(set) var updatedAt: Date
|
||||||
@NSManaged public private(set) var type: String
|
@NSManaged public private(set) var typeRaw: String
|
||||||
@NSManaged public private(set) var account: MastodonUser
|
@NSManaged public private(set) var account: MastodonUser
|
||||||
@NSManaged public private(set) var status: Status?
|
@NSManaged public private(set) var status: Status?
|
||||||
|
|
||||||
|
@NSManaged public private(set) var domain: String
|
||||||
|
@NSManaged public private(set) var userID: String
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonNotification {
|
extension MastodonNotification {
|
||||||
|
@ -26,12 +27,6 @@ extension MastodonNotification {
|
||||||
super.awakeFromInsert()
|
super.awakeFromInsert()
|
||||||
setPrimitiveValue(UUID(), forKey: #keyPath(MastodonNotification.identifier))
|
setPrimitiveValue(UUID(), forKey: #keyPath(MastodonNotification.identifier))
|
||||||
}
|
}
|
||||||
|
|
||||||
public override func willSave() {
|
|
||||||
super.willSave()
|
|
||||||
setPrimitiveValue(Date(), forKey: #keyPath(MastodonNotification.updatedAt))
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension MastodonNotification {
|
public extension MastodonNotification {
|
||||||
|
@ -39,16 +34,19 @@ public extension MastodonNotification {
|
||||||
static func insert(
|
static func insert(
|
||||||
into context: NSManagedObjectContext,
|
into context: NSManagedObjectContext,
|
||||||
domain: String,
|
domain: String,
|
||||||
|
userID: String,
|
||||||
|
networkDate: Date,
|
||||||
property: Property
|
property: Property
|
||||||
) -> MastodonNotification {
|
) -> MastodonNotification {
|
||||||
let notification: MastodonNotification = context.insertObject()
|
let notification: MastodonNotification = context.insertObject()
|
||||||
notification.id = property.id
|
notification.id = property.id
|
||||||
notification.createAt = property.createdAt
|
notification.createAt = property.createdAt
|
||||||
notification.updatedAt = property.createdAt
|
notification.updatedAt = networkDate
|
||||||
notification.type = property.type
|
notification.typeRaw = property.typeRaw
|
||||||
notification.account = property.account
|
notification.account = property.account
|
||||||
notification.status = property.status
|
notification.status = property.status
|
||||||
notification.domain = domain
|
notification.domain = domain
|
||||||
|
notification.userID = userID
|
||||||
return notification
|
return notification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,19 +54,20 @@ public extension MastodonNotification {
|
||||||
public extension MastodonNotification {
|
public extension MastodonNotification {
|
||||||
struct Property {
|
struct Property {
|
||||||
public init(id: String,
|
public init(id: String,
|
||||||
type: String,
|
typeRaw: String,
|
||||||
account: MastodonUser,
|
account: MastodonUser,
|
||||||
status: Status?,
|
status: Status?,
|
||||||
createdAt: Date) {
|
createdAt: Date
|
||||||
|
) {
|
||||||
self.id = id
|
self.id = id
|
||||||
self.type = type
|
self.typeRaw = typeRaw
|
||||||
self.account = account
|
self.account = account
|
||||||
self.status = status
|
self.status = status
|
||||||
self.createdAt = createdAt
|
self.createdAt = createdAt
|
||||||
}
|
}
|
||||||
|
|
||||||
public let id: String
|
public let id: String
|
||||||
public let type: String
|
public let typeRaw: String
|
||||||
public let account: MastodonUser
|
public let account: MastodonUser
|
||||||
public let status: Status?
|
public let status: Status?
|
||||||
public let createdAt: Date
|
public let createdAt: Date
|
||||||
|
@ -76,19 +75,31 @@ public extension MastodonNotification {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension MastodonNotification {
|
extension MastodonNotification {
|
||||||
public static func predicate(domain: String) -> NSPredicate {
|
static func predicate(domain: String) -> NSPredicate {
|
||||||
return NSPredicate(format: "%K == %@", #keyPath(MastodonNotification.domain), domain)
|
return NSPredicate(format: "%K == %@", #keyPath(MastodonNotification.domain), domain)
|
||||||
}
|
}
|
||||||
|
|
||||||
static func predicate(type: String) -> NSPredicate {
|
static func predicate(userID: String) -> NSPredicate {
|
||||||
return NSPredicate(format: "%K == %@", #keyPath(MastodonNotification.type), type)
|
return NSPredicate(format: "%K == %@", #keyPath(MastodonNotification.userID), userID)
|
||||||
}
|
}
|
||||||
|
|
||||||
public static func predicate(domain: String, type: String) -> NSPredicate {
|
static func predicate(typeRaw: String) -> NSPredicate {
|
||||||
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
return NSPredicate(format: "%K == %@", #keyPath(MastodonNotification.typeRaw), typeRaw)
|
||||||
MastodonNotification.predicate(domain: domain),
|
}
|
||||||
MastodonNotification.predicate(type: type)
|
|
||||||
])
|
public static func predicate(domain: String, userID: String, typeRaw: String? = nil) -> NSPredicate {
|
||||||
|
if let typeRaw = typeRaw {
|
||||||
|
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||||
|
MastodonNotification.predicate(domain: domain),
|
||||||
|
MastodonNotification.predicate(typeRaw: typeRaw),
|
||||||
|
MastodonNotification.predicate(userID: userID),
|
||||||
|
])
|
||||||
|
} else {
|
||||||
|
return NSCompoundPredicate(andPredicateWithSubpredicates: [
|
||||||
|
MastodonNotification.predicate(domain: domain),
|
||||||
|
MastodonNotification.predicate(userID: userID)
|
||||||
|
])
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@
|
||||||
2D152A9225C2980C009AA50C /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A9125C2980C009AA50C /* UIFont.swift */; };
|
2D152A9225C2980C009AA50C /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A9125C2980C009AA50C /* UIFont.swift */; };
|
||||||
2D198643261BF09500F0B013 /* SearchResultItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198642261BF09500F0B013 /* SearchResultItem.swift */; };
|
2D198643261BF09500F0B013 /* SearchResultItem.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198642261BF09500F0B013 /* SearchResultItem.swift */; };
|
||||||
2D198649261C0B8500F0B013 /* SearchResultSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198648261C0B8500F0B013 /* SearchResultSection.swift */; };
|
2D198649261C0B8500F0B013 /* SearchResultSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198648261C0B8500F0B013 /* SearchResultSection.swift */; };
|
||||||
2D19864F261C372A00F0B013 /* CommonBottomLoader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D19864E261C372A00F0B013 /* CommonBottomLoader.swift */; };
|
|
||||||
2D198655261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198654261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift */; };
|
2D198655261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D198654261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift */; };
|
||||||
2D206B7225F5D27F00143C56 /* AudioContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D206B7125F5D27F00143C56 /* AudioContainerView.swift */; };
|
2D206B7225F5D27F00143C56 /* AudioContainerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D206B7125F5D27F00143C56 /* AudioContainerView.swift */; };
|
||||||
2D206B8025F5F45E00143C56 /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D206B7F25F5F45E00143C56 /* UIImage.swift */; };
|
2D206B8025F5F45E00143C56 /* UIImage.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D206B7F25F5F45E00143C56 /* UIImage.swift */; };
|
||||||
|
@ -427,7 +426,6 @@
|
||||||
2D152A9125C2980C009AA50C /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
|
2D152A9125C2980C009AA50C /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
|
||||||
2D198642261BF09500F0B013 /* SearchResultItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultItem.swift; sourceTree = "<group>"; };
|
2D198642261BF09500F0B013 /* SearchResultItem.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultItem.swift; sourceTree = "<group>"; };
|
||||||
2D198648261C0B8500F0B013 /* SearchResultSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultSection.swift; sourceTree = "<group>"; };
|
2D198648261C0B8500F0B013 /* SearchResultSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultSection.swift; sourceTree = "<group>"; };
|
||||||
2D19864E261C372A00F0B013 /* CommonBottomLoader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommonBottomLoader.swift; sourceTree = "<group>"; };
|
|
||||||
2D198654261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewModel+LoadOldestState.swift"; sourceTree = "<group>"; };
|
2D198654261C3C4300F0B013 /* SearchViewModel+LoadOldestState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "SearchViewModel+LoadOldestState.swift"; sourceTree = "<group>"; };
|
||||||
2D206B7125F5D27F00143C56 /* AudioContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioContainerView.swift; sourceTree = "<group>"; };
|
2D206B7125F5D27F00143C56 /* AudioContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AudioContainerView.swift; sourceTree = "<group>"; };
|
||||||
2D206B7F25F5F45E00143C56 /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = "<group>"; };
|
2D206B7F25F5F45E00143C56 /* UIImage.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIImage.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1154,7 +1152,6 @@
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */,
|
2DFAD5362617010500F9EE7C /* SearchingTableViewCell.swift */,
|
||||||
2D19864E261C372A00F0B013 /* CommonBottomLoader.swift */,
|
|
||||||
);
|
);
|
||||||
path = TableViewCell;
|
path = TableViewCell;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -2272,7 +2269,6 @@
|
||||||
DBB5256E2612D5A1002F1F29 /* ProfileStatusDashboardView.swift in Sources */,
|
DBB5256E2612D5A1002F1F29 /* ProfileStatusDashboardView.swift in Sources */,
|
||||||
2D24E1232626ED9D00A59D4F /* UIView+Gesture.swift in Sources */,
|
2D24E1232626ED9D00A59D4F /* UIView+Gesture.swift in Sources */,
|
||||||
DB45FAE325CA7181005A8AC7 /* MastodonUser.swift in Sources */,
|
DB45FAE325CA7181005A8AC7 /* MastodonUser.swift in Sources */,
|
||||||
2D19864F261C372A00F0B013 /* CommonBottomLoader.swift in Sources */,
|
|
||||||
DB2FF510260B113300ADA9FE /* ComposeStatusPollExpiresOptionCollectionViewCell.swift in Sources */,
|
DB2FF510260B113300ADA9FE /* ComposeStatusPollExpiresOptionCollectionViewCell.swift in Sources */,
|
||||||
0F202213261351F5000C64BF /* APIService+HashtagTimeline.swift in Sources */,
|
0F202213261351F5000C64BF /* APIService+HashtagTimeline.swift in Sources */,
|
||||||
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */,
|
DB0AC6FC25CD02E600D75117 /* APIService+Instance.swift in Sources */,
|
||||||
|
|
|
@ -17,10 +17,10 @@ enum NotificationItem {
|
||||||
extension NotificationItem: Equatable {
|
extension NotificationItem: Equatable {
|
||||||
static func == (lhs: NotificationItem, rhs: NotificationItem) -> Bool {
|
static func == (lhs: NotificationItem, rhs: NotificationItem) -> Bool {
|
||||||
switch (lhs, rhs) {
|
switch (lhs, rhs) {
|
||||||
case (.bottomLoader, .bottomLoader):
|
|
||||||
return true
|
|
||||||
case (.notification(let idLeft), .notification(let idRight)):
|
case (.notification(let idLeft), .notification(let idRight)):
|
||||||
return idLeft == idRight
|
return idLeft == idRight
|
||||||
|
case (.bottomLoader, .bottomLoader):
|
||||||
|
return true
|
||||||
default:
|
default:
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ extension NotificationSection {
|
||||||
case .notification(let objectID):
|
case .notification(let objectID):
|
||||||
|
|
||||||
let notification = managedObjectContext.object(with: objectID) as! MastodonNotification
|
let notification = managedObjectContext.object(with: objectID) as! MastodonNotification
|
||||||
let type = Mastodon.Entity.Notification.NotificationType(rawValue: notification.type)
|
let type = Mastodon.Entity.Notification.NotificationType(rawValue: notification.typeRaw)
|
||||||
|
|
||||||
let timeText = notification.createAt.shortTimeAgoSinceNow
|
let timeText = notification.createAt.shortTimeAgoSinceNow
|
||||||
|
|
||||||
|
@ -128,7 +128,7 @@ extension NotificationSection {
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: CommonBottomLoader.self)) as! CommonBottomLoader
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) as! TimelineBottomLoaderTableViewCell
|
||||||
cell.startAnimating()
|
cell.startAnimating()
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,7 @@ extension SearchResultSection {
|
||||||
cell.config(with: user)
|
cell.config(with: user)
|
||||||
return cell
|
return cell
|
||||||
case .bottomLoader:
|
case .bottomLoader:
|
||||||
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: CommonBottomLoader.self)) as! CommonBottomLoader
|
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self)) as! TimelineBottomLoaderTableViewCell
|
||||||
cell.startAnimating()
|
cell.startAnimating()
|
||||||
return cell
|
return cell
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,8 +174,9 @@ extension UIView {
|
||||||
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return }
|
guard superview != nil else { assert(false, "Superview cannot be nil when adding contraints"); return }
|
||||||
translatesAutoresizingMaskIntoConstraints = false
|
translatesAutoresizingMaskIntoConstraints = false
|
||||||
constrain([
|
constrain([
|
||||||
widthAnchor.constraint(equalToConstant: toSize.width),
|
widthAnchor.constraint(equalToConstant: toSize.width).priority(.required - 1),
|
||||||
heightAnchor.constraint(equalToConstant: toSize.height)])
|
heightAnchor.constraint(equalToConstant: toSize.height).priority(.required - 1)
|
||||||
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
func pin(top: CGFloat?,left: CGFloat?,bottom: CGFloat?, right: CGFloat?) {
|
func pin(top: CGFloat?,left: CGFloat?,bottom: CGFloat?, right: CGFloat?) {
|
||||||
|
|
|
@ -33,7 +33,7 @@ final class NotificationViewController: UIViewController, NeedsDependency {
|
||||||
tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
tableView.separatorInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
|
||||||
tableView.register(NotificationTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationTableViewCell.self))
|
tableView.register(NotificationTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationTableViewCell.self))
|
||||||
tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self))
|
tableView.register(NotificationStatusTableViewCell.self, forCellReuseIdentifier: String(describing: NotificationStatusTableViewCell.self))
|
||||||
tableView.register(CommonBottomLoader.self, forCellReuseIdentifier: String(describing: CommonBottomLoader.self))
|
tableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
||||||
tableView.tableFooterView = UIView()
|
tableView.tableFooterView = UIView()
|
||||||
tableView.rowHeight = UITableView.automaticDimension
|
tableView.rowHeight = UITableView.automaticDimension
|
||||||
return tableView
|
return tableView
|
||||||
|
@ -111,15 +111,15 @@ extension NotificationViewController {
|
||||||
extension NotificationViewController {
|
extension NotificationViewController {
|
||||||
@objc private func segmentedControlValueChanged(_ sender: UISegmentedControl) {
|
@objc private func segmentedControlValueChanged(_ sender: UISegmentedControl) {
|
||||||
os_log("%{public}s[%{public}ld], %{public}s: select at index: %ld", (#file as NSString).lastPathComponent, #line, #function, sender.selectedSegmentIndex)
|
os_log("%{public}s[%{public}ld], %{public}s: select at index: %ld", (#file as NSString).lastPathComponent, #line, #function, sender.selectedSegmentIndex)
|
||||||
guard let domain = viewModel.activeMastodonAuthenticationBox.value?.domain else {
|
guard let domain = viewModel.activeMastodonAuthenticationBox.value?.domain, let userID = viewModel.activeMastodonAuthenticationBox.value?.userID else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if sender.selectedSegmentIndex == 0 {
|
if sender.selectedSegmentIndex == 0 {
|
||||||
viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
|
viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID)
|
||||||
} else {
|
} else {
|
||||||
viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain, type: Mastodon.Entity.Notification.NotificationType.mention.rawValue)
|
viewModel.notificationPredicate.value = MastodonNotification.predicate(domain: domain,userID: userID, typeRaw: Mastodon.Entity.Notification.NotificationType.mention.rawValue)
|
||||||
}
|
}
|
||||||
viewModel.selectedIndex.value = sender.selectedSegmentIndex
|
viewModel.selectedIndex.value = NotificationViewModel.NotificationSegment.init(rawValue: sender.selectedSegmentIndex)!
|
||||||
}
|
}
|
||||||
|
|
||||||
@objc private func refreshControlValueChanged(_ sender: UIRefreshControl) {
|
@objc private func refreshControlValueChanged(_ sender: UIRefreshControl) {
|
||||||
|
@ -196,7 +196,7 @@ extension NotificationViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
|
extension NotificationViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
typealias BottomLoaderTableViewCell = CommonBottomLoader
|
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
||||||
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
|
typealias LoadingState = NotificationViewModel.LoadOldestState.Loading
|
||||||
var loadMoreConfigurableTableView: UITableView { tableView }
|
var loadMoreConfigurableTableView: UITableView { tableView }
|
||||||
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
|
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
|
||||||
|
|
|
@ -53,12 +53,14 @@ extension NotificationViewModel.LoadLatestState {
|
||||||
sinceID: nil,
|
sinceID: nil,
|
||||||
minID: nil,
|
minID: nil,
|
||||||
limit: nil,
|
limit: nil,
|
||||||
excludeTypes: Mastodon.API.Notifications.allExcludeTypes(),
|
excludeTypes: [.followRequest],
|
||||||
accountID: nil)
|
accountID: nil
|
||||||
|
)
|
||||||
viewModel.context.apiService.allNotifications(
|
viewModel.context.apiService.allNotifications(
|
||||||
domain: activeMastodonAuthenticationBox.domain,
|
domain: activeMastodonAuthenticationBox.domain,
|
||||||
query: query,
|
query: query,
|
||||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox)
|
mastodonAuthenticationBox: activeMastodonAuthenticationBox
|
||||||
|
)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
switch completion {
|
switch completion {
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
|
|
@ -50,7 +50,7 @@ extension NotificationViewModel.LoadOldestState {
|
||||||
}
|
}
|
||||||
let notifications: [MastodonNotification]? = {
|
let notifications: [MastodonNotification]? = {
|
||||||
let request = MastodonNotification.sortedFetchRequest
|
let request = MastodonNotification.sortedFetchRequest
|
||||||
request.predicate = MastodonNotification.predicate(domain: activeMastodonAuthenticationBox.domain)
|
request.predicate = MastodonNotification.predicate(domain: activeMastodonAuthenticationBox.domain, userID: activeMastodonAuthenticationBox.userID)
|
||||||
request.returnsObjectsAsFaults = false
|
request.returnsObjectsAsFaults = false
|
||||||
do {
|
do {
|
||||||
return try self.viewModel?.context.managedObjectContext.fetch(request)
|
return try self.viewModel?.context.managedObjectContext.fetch(request)
|
||||||
|
@ -71,12 +71,13 @@ extension NotificationViewModel.LoadOldestState {
|
||||||
sinceID: nil,
|
sinceID: nil,
|
||||||
minID: nil,
|
minID: nil,
|
||||||
limit: nil,
|
limit: nil,
|
||||||
excludeTypes: Mastodon.API.Notifications.allExcludeTypes(),
|
excludeTypes: [.followRequest],
|
||||||
accountID: nil)
|
accountID: nil)
|
||||||
viewModel.context.apiService.allNotifications(
|
viewModel.context.apiService.allNotifications(
|
||||||
domain: activeMastodonAuthenticationBox.domain,
|
domain: activeMastodonAuthenticationBox.domain,
|
||||||
query: query,
|
query: query,
|
||||||
mastodonAuthenticationBox: activeMastodonAuthenticationBox)
|
mastodonAuthenticationBox: activeMastodonAuthenticationBox
|
||||||
|
)
|
||||||
.sink { completion in
|
.sink { completion in
|
||||||
switch completion {
|
switch completion {
|
||||||
case .failure(let error):
|
case .failure(let error):
|
||||||
|
@ -89,16 +90,17 @@ extension NotificationViewModel.LoadOldestState {
|
||||||
stateMachine.enter(Idle.self)
|
stateMachine.enter(Idle.self)
|
||||||
} receiveValue: { [weak viewModel] response in
|
} receiveValue: { [weak viewModel] response in
|
||||||
guard let viewModel = viewModel else { return }
|
guard let viewModel = viewModel else { return }
|
||||||
if viewModel.selectedIndex.value == 1 {
|
switch viewModel.selectedIndex.value {
|
||||||
viewModel.noMoreNotification.value = response.value.isEmpty
|
case .EveryThing:
|
||||||
let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention }
|
if response.value.isEmpty {
|
||||||
if list.isEmpty {
|
|
||||||
stateMachine.enter(NoMore.self)
|
stateMachine.enter(NoMore.self)
|
||||||
} else {
|
} else {
|
||||||
stateMachine.enter(Idle.self)
|
stateMachine.enter(Idle.self)
|
||||||
}
|
}
|
||||||
} else {
|
case .Mentions:
|
||||||
if response.value.isEmpty {
|
viewModel.noMoreNotification.value = response.value.isEmpty
|
||||||
|
let list = response.value.filter { $0.type == Mastodon.Entity.Notification.NotificationType.mention }
|
||||||
|
if list.isEmpty {
|
||||||
stateMachine.enter(NoMore.self)
|
stateMachine.enter(NoMore.self)
|
||||||
} else {
|
} else {
|
||||||
stateMachine.enter(Idle.self)
|
stateMachine.enter(Idle.self)
|
||||||
|
|
|
@ -22,7 +22,7 @@ final class NotificationViewModel: NSObject {
|
||||||
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
|
weak var contentOffsetAdjustableTimelineViewControllerDelegate: ContentOffsetAdjustableTimelineViewControllerDelegate?
|
||||||
|
|
||||||
let viewDidLoad = PassthroughSubject<Void, Never>()
|
let viewDidLoad = PassthroughSubject<Void, Never>()
|
||||||
let selectedIndex = CurrentValueSubject<Int, Never>(0)
|
let selectedIndex = CurrentValueSubject<NotificationSegment, Never>(.EveryThing)
|
||||||
let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
|
let noMoreNotification = CurrentValueSubject<Bool, Never>(false)
|
||||||
|
|
||||||
let activeMastodonAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
|
let activeMastodonAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
|
||||||
|
@ -88,8 +88,8 @@ final class NotificationViewModel: NSObject {
|
||||||
.sink(receiveValue: { [weak self] box in
|
.sink(receiveValue: { [weak self] box in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
self.activeMastodonAuthenticationBox.value = box
|
self.activeMastodonAuthenticationBox.value = box
|
||||||
if let domain = box?.domain {
|
if let domain = box?.domain, let userID = box?.userID {
|
||||||
self.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
|
self.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
@ -115,9 +115,16 @@ final class NotificationViewModel: NSObject {
|
||||||
viewDidLoad
|
viewDidLoad
|
||||||
.sink { [weak self] in
|
.sink { [weak self] in
|
||||||
|
|
||||||
guard let domain = self?.activeMastodonAuthenticationBox.value?.domain else { return }
|
guard let domain = self?.activeMastodonAuthenticationBox.value?.domain, let userID = self?.activeMastodonAuthenticationBox.value?.userID else { return }
|
||||||
self?.notificationPredicate.value = MastodonNotification.predicate(domain: domain)
|
self?.notificationPredicate.value = MastodonNotification.predicate(domain: domain, userID: userID)
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension NotificationViewModel {
|
||||||
|
enum NotificationSegment: Int {
|
||||||
|
case EveryThing
|
||||||
|
case Mentions
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -103,7 +103,6 @@ final class NotificationStatusTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
extension NotificationStatusTableViewCell {
|
extension NotificationStatusTableViewCell {
|
||||||
func configure() {
|
func configure() {
|
||||||
selectionStyle = .none
|
|
||||||
|
|
||||||
let container = UIView()
|
let container = UIView()
|
||||||
container.backgroundColor = .clear
|
container.backgroundColor = .clear
|
||||||
|
@ -117,11 +116,11 @@ extension NotificationStatusTableViewCell {
|
||||||
|
|
||||||
container.addSubview(avatatImageView)
|
container.addSubview(avatatImageView)
|
||||||
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
|
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
|
||||||
avatatImageView.pin(top: 12, left: 12, bottom: nil, right: nil)
|
avatatImageView.pin(top: 12, left: 0, bottom: nil, right: nil)
|
||||||
|
|
||||||
container.addSubview(actionImageBackground)
|
container.addSubview(actionImageBackground)
|
||||||
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
|
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
|
||||||
actionImageBackground.pin(top: 33, left: 33, bottom: nil, right: nil)
|
actionImageBackground.pin(top: 33, left: 21, bottom: nil, right: nil)
|
||||||
|
|
||||||
actionImageBackground.addSubview(actionImageView)
|
actionImageBackground.addSubview(actionImageView)
|
||||||
actionImageView.constrainToCenter()
|
actionImageView.constrainToCenter()
|
||||||
|
@ -130,22 +129,21 @@ extension NotificationStatusTableViewCell {
|
||||||
nameLabel.constrain([
|
nameLabel.constrain([
|
||||||
nameLabel.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
|
nameLabel.topAnchor.constraint(equalTo: container.topAnchor, constant: 12),
|
||||||
nameLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 61)
|
nameLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 61)
|
||||||
|
|
||||||
])
|
])
|
||||||
|
|
||||||
container.addSubview(actionLabel)
|
container.addSubview(actionLabel)
|
||||||
actionLabel.constrain([
|
actionLabel.constrain([
|
||||||
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
|
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
|
||||||
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
|
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
|
||||||
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4).priority(.defaultLow)
|
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4)
|
||||||
])
|
])
|
||||||
|
|
||||||
statusView.contentWarningBlurContentImageView.backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color
|
statusView.contentWarningBlurContentImageView.backgroundColor = Asset.Colors.Background.secondaryGroupedSystemBackground.color
|
||||||
statusView.isUserInteractionEnabled = false
|
statusView.isUserInteractionEnabled = false
|
||||||
// remove item don't display
|
// remove item don't display
|
||||||
statusView.actionToolbarContainer.removeFromSuperview()
|
statusView.actionToolbarContainer.isHidden = true
|
||||||
statusView.avatarView.removeFromSuperview()
|
statusView.avatarView.isHidden = true
|
||||||
statusView.usernameLabel.removeFromSuperview()
|
statusView.usernameLabel.isHidden = true
|
||||||
|
|
||||||
container.addSubview(statusBorder)
|
container.addSubview(statusBorder)
|
||||||
statusBorder.pin(top: 40, left: 63, bottom: 14, right: 14)
|
statusBorder.pin(top: 40, left: 63, bottom: 14, right: 14)
|
||||||
|
|
|
@ -85,7 +85,6 @@ final class NotificationTableViewCell: UITableViewCell {
|
||||||
|
|
||||||
extension NotificationTableViewCell {
|
extension NotificationTableViewCell {
|
||||||
func configure() {
|
func configure() {
|
||||||
selectionStyle = .none
|
|
||||||
|
|
||||||
let container = UIView()
|
let container = UIView()
|
||||||
container.backgroundColor = .clear
|
container.backgroundColor = .clear
|
||||||
|
@ -99,7 +98,7 @@ extension NotificationTableViewCell {
|
||||||
|
|
||||||
container.addSubview(avatatImageView)
|
container.addSubview(avatatImageView)
|
||||||
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
|
avatatImageView.pin(toSize: CGSize(width: 35, height: 35))
|
||||||
avatatImageView.pin(top: 12, left: 12, bottom: nil, right: nil)
|
avatatImageView.pin(top: 12, left: 0, bottom: nil, right: nil)
|
||||||
|
|
||||||
container.addSubview(actionImageBackground)
|
container.addSubview(actionImageBackground)
|
||||||
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
|
actionImageBackground.pin(toSize: CGSize(width: 24 + NotificationTableViewCell.actionImageBorderWidth, height: 24 + NotificationTableViewCell.actionImageBorderWidth))
|
||||||
|
@ -119,7 +118,7 @@ extension NotificationTableViewCell {
|
||||||
actionLabel.constrain([
|
actionLabel.constrain([
|
||||||
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
|
actionLabel.leadingAnchor.constraint(equalTo: nameLabel.trailingAnchor, constant: 4),
|
||||||
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
|
actionLabel.centerYAnchor.constraint(equalTo: nameLabel.centerYAnchor),
|
||||||
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4).priority(.defaultLow)
|
container.trailingAnchor.constraint(greaterThanOrEqualTo: actionLabel.trailingAnchor, constant: 4)
|
||||||
])
|
])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,7 @@ extension SearchViewController {
|
||||||
func setupSearchingTableView() {
|
func setupSearchingTableView() {
|
||||||
searchingTableView.delegate = self
|
searchingTableView.delegate = self
|
||||||
searchingTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: String(describing: SearchingTableViewCell.self))
|
searchingTableView.register(SearchingTableViewCell.self, forCellReuseIdentifier: String(describing: SearchingTableViewCell.self))
|
||||||
searchingTableView.register(CommonBottomLoader.self, forCellReuseIdentifier: String(describing: CommonBottomLoader.self))
|
searchingTableView.register(TimelineBottomLoaderTableViewCell.self, forCellReuseIdentifier: String(describing: TimelineBottomLoaderTableViewCell.self))
|
||||||
view.addSubview(searchingTableView)
|
view.addSubview(searchingTableView)
|
||||||
searchingTableView.constrain([
|
searchingTableView.constrain([
|
||||||
searchingTableView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor),
|
searchingTableView.frameLayoutGuide.topAnchor.constraint(equalTo: searchBar.bottomAnchor),
|
||||||
|
|
|
@ -227,7 +227,7 @@ extension SearchViewController: UISearchBarDelegate {
|
||||||
}
|
}
|
||||||
|
|
||||||
extension SearchViewController: LoadMoreConfigurableTableViewContainer {
|
extension SearchViewController: LoadMoreConfigurableTableViewContainer {
|
||||||
typealias BottomLoaderTableViewCell = CommonBottomLoader
|
typealias BottomLoaderTableViewCell = TimelineBottomLoaderTableViewCell
|
||||||
typealias LoadingState = SearchViewModel.LoadOldestState.Loading
|
typealias LoadingState = SearchViewModel.LoadOldestState.Loading
|
||||||
var loadMoreConfigurableTableView: UITableView { searchingTableView }
|
var loadMoreConfigurableTableView: UITableView { searchingTableView }
|
||||||
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
|
var loadMoreConfigurableStateMachine: GKStateMachine { viewModel.loadoldestStateMachine }
|
||||||
|
|
|
@ -1,47 +0,0 @@
|
||||||
//
|
|
||||||
// CommonBottomLoader.swift
|
|
||||||
// Mastodon
|
|
||||||
//
|
|
||||||
// Created by sxiaojian on 2021/4/6.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Foundation
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
final class CommonBottomLoader: UITableViewCell {
|
|
||||||
let activityIndicatorView: UIActivityIndicatorView = {
|
|
||||||
let activityIndicatorView = UIActivityIndicatorView(style: .medium)
|
|
||||||
activityIndicatorView.tintColor = Asset.Colors.Label.primary.color
|
|
||||||
activityIndicatorView.hidesWhenStopped = true
|
|
||||||
return activityIndicatorView
|
|
||||||
}()
|
|
||||||
|
|
||||||
override func prepareForReuse() {
|
|
||||||
super.prepareForReuse()
|
|
||||||
}
|
|
||||||
|
|
||||||
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
|
|
||||||
super.init(style: style, reuseIdentifier: reuseIdentifier)
|
|
||||||
_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
|
||||||
super.init(coder: coder)
|
|
||||||
_init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func startAnimating() {
|
|
||||||
activityIndicatorView.startAnimating()
|
|
||||||
}
|
|
||||||
|
|
||||||
func stopAnimating() {
|
|
||||||
activityIndicatorView.stopAnimating()
|
|
||||||
}
|
|
||||||
|
|
||||||
func _init() {
|
|
||||||
selectionStyle = .none
|
|
||||||
backgroundColor = Asset.Colors.Background.systemGroupedBackground.color
|
|
||||||
contentView.addSubview(activityIndicatorView)
|
|
||||||
activityIndicatorView.constrainToCenter()
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -16,48 +16,52 @@ extension APIService {
|
||||||
func allNotifications(
|
func allNotifications(
|
||||||
domain: String,
|
domain: String,
|
||||||
query: Mastodon.API.Notifications.Query,
|
query: Mastodon.API.Notifications.Query,
|
||||||
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error>
|
mastodonAuthenticationBox: AuthenticationService.MastodonAuthenticationBox
|
||||||
{
|
) -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error> {
|
||||||
let authorization = mastodonAuthenticationBox.userAuthorization
|
let authorization = mastodonAuthenticationBox.userAuthorization
|
||||||
|
let userID = mastodonAuthenticationBox.userID
|
||||||
return Mastodon.API.Notifications.getNotifications(
|
return Mastodon.API.Notifications.getNotifications(
|
||||||
session: session,
|
session: session,
|
||||||
domain: domain,
|
domain: domain,
|
||||||
query: query,
|
query: query,
|
||||||
authorization: authorization)
|
authorization: authorization
|
||||||
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error> in
|
)
|
||||||
let log = OSLog.api
|
.flatMap { response -> AnyPublisher<Mastodon.Response.Content<[Mastodon.Entity.Notification]>, Error> in
|
||||||
return self.backgroundManagedObjectContext.performChanges {
|
let log = OSLog.api
|
||||||
response.value.forEach { notification in
|
return self.backgroundManagedObjectContext.performChanges {
|
||||||
let (mastodonUser, _) = APIService.CoreData.createOrMergeMastodonUser(into: self.backgroundManagedObjectContext, for: nil, in: domain, entity: notification.account, userCache: nil, networkDate: Date(), log: log)
|
response.value.forEach { notification in
|
||||||
var status: Status?
|
let (mastodonUser, _) = APIService.CoreData.createOrMergeMastodonUser(into: self.backgroundManagedObjectContext, for: nil, in: domain, entity: notification.account, userCache: nil, networkDate: Date(), log: log)
|
||||||
if let statusEntity = notification.status {
|
var status: Status?
|
||||||
let (statusInCoreData, _, _) = APIService.CoreData.createOrMergeStatus(
|
if let statusEntity = notification.status {
|
||||||
into: self.backgroundManagedObjectContext,
|
let (statusInCoreData, _, _) = APIService.CoreData.createOrMergeStatus(
|
||||||
for: nil,
|
into: self.backgroundManagedObjectContext,
|
||||||
domain: domain,
|
for: nil,
|
||||||
entity: statusEntity,
|
domain: domain,
|
||||||
statusCache: nil,
|
entity: statusEntity,
|
||||||
userCache: nil,
|
statusCache: nil,
|
||||||
networkDate: Date(),
|
userCache: nil,
|
||||||
log: log)
|
networkDate: Date(),
|
||||||
status = statusInCoreData
|
log: log
|
||||||
}
|
)
|
||||||
// use constrain to avoid repeated save
|
status = statusInCoreData
|
||||||
let notification = MastodonNotification.insert(into: self.backgroundManagedObjectContext, domain: domain, property: MastodonNotification.Property(id: notification.id, type: notification.type.rawValue, account: mastodonUser, status: status, createdAt: notification.createdAt))
|
|
||||||
os_log(.info, log: log, "%{public}s[%{public}ld], %{public}s: fetch mastodon user [%s](%s)", (#file as NSString).lastPathComponent, #line, #function, notification.type, notification.account.username)
|
|
||||||
}
|
}
|
||||||
|
// use constrain to avoid repeated save
|
||||||
|
let property = MastodonNotification.Property(id: notification.id, typeRaw: notification.type.rawValue, account: mastodonUser, status: status, createdAt: notification.createdAt)
|
||||||
|
let notification = MastodonNotification.insert(into: self.backgroundManagedObjectContext, domain: domain, userID: userID, networkDate: response.networkDate, property: property)
|
||||||
|
os_log(.info, log: log, "%{public}s[%{public}ld], %{public}s: fetch mastodon user [%s](%s)", (#file as NSString).lastPathComponent, #line, #function, notification.typeRaw, notification.account.username)
|
||||||
}
|
}
|
||||||
.setFailureType(to: Error.self)
|
}
|
||||||
.tryMap { result -> Mastodon.Response.Content<[Mastodon.Entity.Notification]> in
|
.setFailureType(to: Error.self)
|
||||||
switch result {
|
.tryMap { result -> Mastodon.Response.Content<[Mastodon.Entity.Notification]> in
|
||||||
case .success:
|
switch result {
|
||||||
return response
|
case .success:
|
||||||
case .failure(let error):
|
return response
|
||||||
throw error
|
case .failure(let error):
|
||||||
}
|
throw error
|
||||||
}
|
}
|
||||||
.eraseToAnyPublisher()
|
|
||||||
}
|
}
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
|
}
|
||||||
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
import Combine
|
import Combine
|
||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
public extension Mastodon.API.Notifications {
|
extension Mastodon.API.Notifications {
|
||||||
internal static func notificationsEndpointURL(domain: String) -> URL {
|
internal static func notificationsEndpointURL(domain: String) -> URL {
|
||||||
Mastodon.API.endpointURL(domain: domain).appendingPathComponent("notifications")
|
Mastodon.API.endpointURL(domain: domain).appendingPathComponent("notifications")
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public extension Mastodon.API.Notifications {
|
||||||
/// - query: `NotificationsQuery` with query parameters
|
/// - query: `NotificationsQuery` with query parameters
|
||||||
/// - authorization: User token
|
/// - authorization: User token
|
||||||
/// - Returns: `AnyPublisher` contains `Token` nested in the response
|
/// - Returns: `AnyPublisher` contains `Token` nested in the response
|
||||||
static func getNotifications(
|
public static func getNotifications(
|
||||||
session: URLSession,
|
session: URLSession,
|
||||||
domain: String,
|
domain: String,
|
||||||
query: Mastodon.API.Notifications.Query,
|
query: Mastodon.API.Notifications.Query,
|
||||||
|
@ -64,7 +64,7 @@ public extension Mastodon.API.Notifications {
|
||||||
/// - notificationID: ID of the notification.
|
/// - notificationID: ID of the notification.
|
||||||
/// - authorization: User token
|
/// - authorization: User token
|
||||||
/// - Returns: `AnyPublisher` contains `Token` nested in the response
|
/// - Returns: `AnyPublisher` contains `Token` nested in the response
|
||||||
static func getNotification(
|
public static func getNotification(
|
||||||
session: URLSession,
|
session: URLSession,
|
||||||
domain: String,
|
domain: String,
|
||||||
notificationID: String,
|
notificationID: String,
|
||||||
|
@ -82,18 +82,10 @@ public extension Mastodon.API.Notifications {
|
||||||
}
|
}
|
||||||
.eraseToAnyPublisher()
|
.eraseToAnyPublisher()
|
||||||
}
|
}
|
||||||
|
|
||||||
static func allExcludeTypes() -> [Mastodon.Entity.Notification.NotificationType] {
|
|
||||||
[.followRequest]
|
|
||||||
}
|
|
||||||
|
|
||||||
static func mentionsExcludeTypes() -> [Mastodon.Entity.Notification.NotificationType] {
|
|
||||||
[.follow, .followRequest, .favourite, .reblog, .poll]
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public extension Mastodon.API.Notifications {
|
extension Mastodon.API.Notifications {
|
||||||
struct Query: Codable, PagedQueryType, GetQuery {
|
public struct Query: PagedQueryType, GetQuery {
|
||||||
public let maxID: Mastodon.Entity.Status.ID?
|
public let maxID: Mastodon.Entity.Status.ID?
|
||||||
public let sinceID: Mastodon.Entity.Status.ID?
|
public let sinceID: Mastodon.Entity.Status.ID?
|
||||||
public let minID: Mastodon.Entity.Status.ID?
|
public let minID: Mastodon.Entity.Status.ID?
|
||||||
|
|
Loading…
Reference in New Issue