fix: tag and searchHistory repeated save in CoreDate
This commit is contained in:
parent
27b698a97a
commit
0dab9acd91
|
@ -149,6 +149,7 @@
|
|||
<entity name="SearchHistory" representedClassName=".SearchHistory" syncable="YES">
|
||||
<attribute name="createAt" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<relationship name="account" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="MastodonUser"/>
|
||||
<relationship name="hashtag" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="Tag"/>
|
||||
</entity>
|
||||
|
@ -194,24 +195,25 @@
|
|||
<attribute name="createAt" attributeType="Date" defaultDateTimeInterval="631123200" usesScalarValueType="NO"/>
|
||||
<attribute name="identifier" attributeType="UUID" usesScalarValueType="NO"/>
|
||||
<attribute name="name" attributeType="String"/>
|
||||
<attribute name="updatedAt" optional="YES" attributeType="Date" usesScalarValueType="NO"/>
|
||||
<attribute name="url" attributeType="String"/>
|
||||
<relationship name="histories" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="History" inverseName="tag" inverseEntity="History"/>
|
||||
<relationship name="statuses" optional="YES" toMany="YES" deletionRule="Nullify" destinationEntity="Status" inverseName="tags" inverseEntity="Status"/>
|
||||
</entity>
|
||||
<elements>
|
||||
<element name="Application" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Attachment" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Emoji" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="History" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="MastodonAuthentication" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="MastodonUser" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Mention" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Poll" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="PollOption" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="PrivateNote" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="SearchHistory" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Status" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Tag" positionX="0" positionY="0" width="0" height="0"/>
|
||||
<element name="Application" positionX="0" positionY="0" width="128" height="104"/>
|
||||
<element name="Attachment" positionX="0" positionY="0" width="128" height="254"/>
|
||||
<element name="Emoji" positionX="0" positionY="0" width="128" height="149"/>
|
||||
<element name="History" positionX="0" positionY="0" width="128" height="119"/>
|
||||
<element name="HomeTimelineIndex" positionX="0" positionY="0" width="128" height="134"/>
|
||||
<element name="MastodonAuthentication" positionX="0" positionY="0" width="128" height="209"/>
|
||||
<element name="MastodonUser" positionX="0" positionY="0" width="128" height="659"/>
|
||||
<element name="Mention" positionX="0" positionY="0" width="128" height="134"/>
|
||||
<element name="Poll" positionX="0" positionY="0" width="128" height="194"/>
|
||||
<element name="PollOption" positionX="0" positionY="0" width="128" height="134"/>
|
||||
<element name="PrivateNote" positionX="0" positionY="0" width="128" height="89"/>
|
||||
<element name="SearchHistory" positionX="0" positionY="0" width="128" height="104"/>
|
||||
<element name="Status" positionX="0" positionY="0" width="128" height="569"/>
|
||||
<element name="Tag" positionX="0" positionY="0" width="128" height="134"/>
|
||||
</elements>
|
||||
</model>
|
|
@ -40,6 +40,26 @@ public extension History {
|
|||
}
|
||||
}
|
||||
|
||||
public extension History {
|
||||
func update(day: Date) {
|
||||
if self.day != day {
|
||||
self.day = day
|
||||
}
|
||||
}
|
||||
|
||||
func update(uses: String) {
|
||||
if self.uses != uses {
|
||||
self.uses = uses
|
||||
}
|
||||
}
|
||||
|
||||
func update(accounts: String) {
|
||||
if self.accounts != accounts {
|
||||
self.accounts = accounts
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public extension History {
|
||||
struct Property {
|
||||
public let day: Date
|
||||
|
|
|
@ -12,6 +12,7 @@ public final class SearchHistory: NSManagedObject {
|
|||
public typealias ID = UUID
|
||||
@NSManaged public private(set) var identifier: ID
|
||||
@NSManaged public private(set) var createAt: Date
|
||||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
||||
@NSManaged public private(set) var account: MastodonUser?
|
||||
@NSManaged public private(set) var hashtag: Tag?
|
||||
|
@ -22,6 +23,13 @@ extension SearchHistory {
|
|||
public override func awakeFromInsert() {
|
||||
super.awakeFromInsert()
|
||||
setPrimitiveValue(UUID(), forKey: #keyPath(SearchHistory.identifier))
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.createAt))
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt))
|
||||
}
|
||||
|
||||
public override func willSave() {
|
||||
super.willSave()
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(SearchHistory.updatedAt))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
|
@ -31,7 +39,6 @@ extension SearchHistory {
|
|||
) -> SearchHistory {
|
||||
let searchHistory: SearchHistory = context.insertObject()
|
||||
searchHistory.account = account
|
||||
searchHistory.createAt = Date()
|
||||
return searchHistory
|
||||
}
|
||||
|
||||
|
@ -42,13 +49,18 @@ extension SearchHistory {
|
|||
) -> SearchHistory {
|
||||
let searchHistory: SearchHistory = context.insertObject()
|
||||
searchHistory.hashtag = hashtag
|
||||
searchHistory.createAt = Date()
|
||||
return searchHistory
|
||||
}
|
||||
}
|
||||
|
||||
public extension SearchHistory {
|
||||
func update(updatedAt: Date) {
|
||||
setValue(updatedAt, forKey: #keyPath(SearchHistory.updatedAt))
|
||||
}
|
||||
}
|
||||
|
||||
extension SearchHistory: Managed {
|
||||
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||
return [NSSortDescriptor(keyPath: \SearchHistory.createAt, ascending: false)]
|
||||
return [NSSortDescriptor(keyPath: \SearchHistory.updatedAt, ascending: false)]
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ public final class Tag: NSManagedObject {
|
|||
public typealias ID = UUID
|
||||
@NSManaged public private(set) var identifier: ID
|
||||
@NSManaged public private(set) var createAt: Date
|
||||
@NSManaged public private(set) var updatedAt: Date
|
||||
|
||||
@NSManaged public private(set) var name: String
|
||||
@NSManaged public private(set) var url: String
|
||||
|
@ -23,14 +24,21 @@ public final class Tag: NSManagedObject {
|
|||
@NSManaged public private(set) var histories: Set<History>?
|
||||
}
|
||||
|
||||
extension Tag {
|
||||
public override func awakeFromInsert() {
|
||||
public extension Tag {
|
||||
override func awakeFromInsert() {
|
||||
super.awakeFromInsert()
|
||||
setPrimitiveValue(UUID(), forKey: #keyPath(Tag.identifier))
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(Tag.createAt))
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(Tag.updatedAt))
|
||||
}
|
||||
|
||||
override func willSave() {
|
||||
super.willSave()
|
||||
setPrimitiveValue(Date(), forKey: #keyPath(Tag.updatedAt))
|
||||
}
|
||||
|
||||
@discardableResult
|
||||
public static func insert(
|
||||
static func insert(
|
||||
into context: NSManagedObjectContext,
|
||||
property: Property
|
||||
) -> Tag {
|
||||
|
@ -44,8 +52,8 @@ extension Tag {
|
|||
}
|
||||
}
|
||||
|
||||
extension Tag {
|
||||
public struct Property {
|
||||
public extension Tag {
|
||||
struct Property {
|
||||
public let name: String
|
||||
public let url: String
|
||||
public let histories: [History]?
|
||||
|
@ -58,8 +66,36 @@ extension Tag {
|
|||
}
|
||||
}
|
||||
|
||||
extension Tag: Managed {
|
||||
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||
return [NSSortDescriptor(keyPath: \Tag.createAt, ascending: false)]
|
||||
public extension Tag {
|
||||
func updateHistory(index: Int, day: Date, uses: String, account: String) {
|
||||
guard let histories = self.histories?.sorted(by: {
|
||||
$0.createAt.compare($1.createAt) == .orderedAscending
|
||||
}) else { return }
|
||||
let history = histories[index]
|
||||
history.update(day: day)
|
||||
history.update(uses: uses)
|
||||
history.update(accounts: account)
|
||||
}
|
||||
|
||||
func appendHistory(history: History) {
|
||||
self.mutableSetValue(forKeyPath: #keyPath(Tag.histories)).add(history)
|
||||
}
|
||||
|
||||
func update(url: String) {
|
||||
if self.url != url {
|
||||
self.url = url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extension Tag: Managed {
|
||||
public static var defaultSortDescriptors: [NSSortDescriptor] {
|
||||
[NSSortDescriptor(keyPath: \Tag.createAt, ascending: false)]
|
||||
}
|
||||
}
|
||||
|
||||
public extension Tag {
|
||||
static func predicate(name: String) -> NSPredicate {
|
||||
NSPredicate(format: "%K == %@", #keyPath(Tag.name), name)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,7 +30,6 @@
|
|||
0FB3D33825E6401400AAD544 /* PickServerCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0FB3D33725E6401400AAD544 /* PickServerCell.swift */; };
|
||||
18BC7629F65E6DB12CB8416D /* Pods_Mastodon_MastodonUITests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3C030226D3C73DCC23D67452 /* Pods_Mastodon_MastodonUITests.framework */; };
|
||||
2D04F42525C255B9003F936F /* APIService+PublicTimeline.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */; };
|
||||
2D0B7A0B261D5A5600B44727 /* Array.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0B7A0A261D5A5600B44727 /* Array.swift */; };
|
||||
2D0B7A1D261D839600B44727 /* SearchHistory.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D0B7A1C261D839600B44727 /* SearchHistory.swift */; };
|
||||
2D152A8C25C295CC009AA50C /* StatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A8B25C295CC009AA50C /* StatusView.swift */; };
|
||||
2D152A9225C2980C009AA50C /* UIFont.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D152A9125C2980C009AA50C /* UIFont.swift */; };
|
||||
|
@ -92,6 +91,7 @@
|
|||
2D76319F25C1521200929FB9 /* StatusSection.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D76319E25C1521200929FB9 /* StatusSection.swift */; };
|
||||
2D7631A825C1535600929FB9 /* StatusTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */; };
|
||||
2D7631B325C159F700929FB9 /* Item.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D7631B225C159F700929FB9 /* Item.swift */; };
|
||||
2D79E701261EA5550011E398 /* APIService+CoreData+Tag.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D79E700261EA5550011E398 /* APIService+CoreData+Tag.swift */; };
|
||||
2D82B9FF25E7863200E36F0F /* OnboardingViewControllerAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */; };
|
||||
2D82BA0525E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D82BA0425E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift */; };
|
||||
2D8434F525FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2D8434F425FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift */; };
|
||||
|
@ -401,7 +401,6 @@
|
|||
0FB3D33125E5F50E00AAD544 /* PickServerSearchCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerSearchCell.swift; sourceTree = "<group>"; };
|
||||
0FB3D33725E6401400AAD544 /* PickServerCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PickServerCell.swift; sourceTree = "<group>"; };
|
||||
2D04F42425C255B9003F936F /* APIService+PublicTimeline.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+PublicTimeline.swift"; sourceTree = "<group>"; };
|
||||
2D0B7A0A261D5A5600B44727 /* Array.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Array.swift; sourceTree = "<group>"; };
|
||||
2D0B7A1C261D839600B44727 /* SearchHistory.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchHistory.swift; sourceTree = "<group>"; };
|
||||
2D152A8B25C295CC009AA50C /* StatusView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusView.swift; sourceTree = "<group>"; };
|
||||
2D152A9125C2980C009AA50C /* UIFont.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UIFont.swift; sourceTree = "<group>"; };
|
||||
|
@ -460,6 +459,7 @@
|
|||
2D76319E25C1521200929FB9 /* StatusSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusSection.swift; sourceTree = "<group>"; };
|
||||
2D7631A725C1535600929FB9 /* StatusTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = StatusTableViewCell.swift; sourceTree = "<group>"; };
|
||||
2D7631B225C159F700929FB9 /* Item.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Item.swift; sourceTree = "<group>"; };
|
||||
2D79E700261EA5550011E398 /* APIService+CoreData+Tag.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "APIService+CoreData+Tag.swift"; sourceTree = "<group>"; };
|
||||
2D82B9FE25E7863200E36F0F /* OnboardingViewControllerAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingViewControllerAppearance.swift; sourceTree = "<group>"; };
|
||||
2D82BA0425E7897700E36F0F /* MastodonResendEmailViewModelNavigationDelegateShim.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonResendEmailViewModelNavigationDelegateShim.swift; sourceTree = "<group>"; };
|
||||
2D8434F425FF465D00EECE90 /* HomeTimelineNavigationBarTitleViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HomeTimelineNavigationBarTitleViewModel.swift; sourceTree = "<group>"; };
|
||||
|
@ -1321,6 +1321,7 @@
|
|||
2D69D00925CAA00300C3A1B2 /* APIService+CoreData+Status.swift */,
|
||||
DB45FADC25CA6F6B005A8AC7 /* APIService+CoreData+MastodonUser.swift */,
|
||||
DB45FAF825CA80A2005A8AC7 /* APIService+CoreData+MastodonAuthentication.swift */,
|
||||
2D79E700261EA5550011E398 /* APIService+CoreData+Tag.swift */,
|
||||
);
|
||||
path = CoreData;
|
||||
sourceTree = "<group>";
|
||||
|
@ -1550,7 +1551,6 @@
|
|||
2D46975D25C2A54100CF4AA9 /* NSLayoutConstraint.swift */,
|
||||
DB68586325E619B700F0A850 /* NSKeyValueObservation.swift */,
|
||||
DB0140CE25C42AEE00F9F3CF /* OSLog.swift */,
|
||||
2D0B7A0A261D5A5600B44727 /* Array.swift */,
|
||||
DB68A06225E905E000CFDF14 /* UIApplication.swift */,
|
||||
DB45FAB525CA5485005A8AC7 /* UIAlertController.swift */,
|
||||
2D42FF8E25C8228A004A627A /* UIButton.swift */,
|
||||
|
@ -2207,6 +2207,7 @@
|
|||
2DE0FACE2615F7AD00CDF649 /* RecommendAccountSection.swift in Sources */,
|
||||
DB49A62B25FF36C700B98345 /* APIService+CustomEmoji.swift in Sources */,
|
||||
DBCBED1D26132E1A00B49291 /* StatusFetchedResultsController.swift in Sources */,
|
||||
2D79E701261EA5550011E398 /* APIService+CoreData+Tag.swift in Sources */,
|
||||
2D939AB525EDD8A90076FA61 /* String.swift in Sources */,
|
||||
DB4481B925EE289600BEFB67 /* UITableView.swift in Sources */,
|
||||
DBE3CDBB261C427900430CC6 /* TimelineHeaderTableViewCell.swift in Sources */,
|
||||
|
@ -2284,7 +2285,6 @@
|
|||
2D939AE825EE1CF80076FA61 /* MastodonRegisterViewController+Avatar.swift in Sources */,
|
||||
DB1D186C25EF5BA7003F1F23 /* PollTableView.swift in Sources */,
|
||||
2D5981A125E4A593000FB903 /* MastodonConfirmEmailViewModel.swift in Sources */,
|
||||
2D0B7A0B261D5A5600B44727 /* Array.swift in Sources */,
|
||||
DB87D4452609BE0500D12C0D /* ComposeStatusPollOptionCollectionViewCell.swift in Sources */,
|
||||
DB8AF55025C13703002E6C99 /* MainTabBarController.swift in Sources */,
|
||||
DB9D6BE925E4F5340051B173 /* SearchViewController.swift in Sources */,
|
||||
|
|
|
@ -1,20 +0,0 @@
|
|||
//
|
||||
// Array.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by sxiaojian on 2021/4/7.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
public extension Array where Element: Equatable {
|
||||
|
||||
func removeDuplicate() -> Array {
|
||||
return self.enumerated().filter { (index,value) -> Bool in
|
||||
return self.firstIndex(of: value) == index
|
||||
}.map { (_, value) in
|
||||
value
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -82,7 +82,8 @@ extension SearchRecommendTagsCollectionViewCell {
|
|||
peopleLabel.text = ""
|
||||
return
|
||||
}
|
||||
let recentHistory = historys[0...2]
|
||||
|
||||
let recentHistory = historys.prefix(2)
|
||||
let peopleAreTalking = recentHistory.compactMap({ Int($0.accounts) }).reduce(0, +)
|
||||
let string = L10n.Scene.Search.Recommend.HashTag.peopleTalking(String(peopleAreTalking))
|
||||
peopleLabel.text = string
|
||||
|
|
|
@ -89,7 +89,8 @@ extension SearchViewModel.LoadOldestState {
|
|||
var newAccounts = [Mastodon.Entity.Account]()
|
||||
newAccounts.append(contentsOf: oldSearchResult.accounts)
|
||||
newAccounts.append(contentsOf: result.value.accounts)
|
||||
viewModel.searchResult.value = Mastodon.Entity.SearchResult(accounts: newAccounts.removeDuplicate(), statuses: oldSearchResult.statuses, hashtags: oldSearchResult.hashtags)
|
||||
newAccounts.removeDuplicates()
|
||||
viewModel.searchResult.value = Mastodon.Entity.SearchResult(accounts: newAccounts, statuses: oldSearchResult.statuses, hashtags: oldSearchResult.hashtags)
|
||||
stateMachine.enter(Idle.self)
|
||||
}
|
||||
case Mastodon.API.Search.SearchType.hashtags:
|
||||
|
@ -99,7 +100,8 @@ extension SearchViewModel.LoadOldestState {
|
|||
var newTags = [Mastodon.Entity.Tag]()
|
||||
newTags.append(contentsOf: oldSearchResult.hashtags)
|
||||
newTags.append(contentsOf: result.value.hashtags)
|
||||
viewModel.searchResult.value = Mastodon.Entity.SearchResult(accounts: oldSearchResult.accounts, statuses: oldSearchResult.statuses, hashtags: newTags.removeDuplicate())
|
||||
newTags.removeDuplicates()
|
||||
viewModel.searchResult.value = Mastodon.Entity.SearchResult(accounts: oldSearchResult.accounts, statuses: oldSearchResult.statuses, hashtags: newTags)
|
||||
stateMachine.enter(Idle.self)
|
||||
}
|
||||
default:
|
||||
|
|
|
@ -234,6 +234,7 @@ final class SearchViewModel: NSObject {
|
|||
}
|
||||
|
||||
func saveItemToCoreData(item: SearchResultItem) {
|
||||
let searchHistories = self.fetchSearchHistory()
|
||||
_ = context.managedObjectContext.performChanges { [weak self] in
|
||||
guard let self = self else { return }
|
||||
switch item {
|
||||
|
@ -255,15 +256,55 @@ final class SearchViewModel: NSObject {
|
|||
}
|
||||
}()
|
||||
let (mastodonUser, _) = APIService.CoreData.createOrMergeMastodonUser(into: self.context.managedObjectContext, for: requestMastodonUser, in: activeMastodonAuthenticationBox.domain, entity: account, userCache: nil, networkDate: Date(), log: OSLog.api)
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, account: mastodonUser)
|
||||
if let searchHistories = searchHistories {
|
||||
let history = searchHistories.first { history -> Bool in
|
||||
guard let account = history.account else { return false }
|
||||
return account.objectID == mastodonUser.objectID
|
||||
}
|
||||
if let history = history {
|
||||
history.update(updatedAt: Date())
|
||||
} else {
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, account: mastodonUser)
|
||||
}
|
||||
} else {
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, account: mastodonUser)
|
||||
}
|
||||
|
||||
case .hashtag(let tag):
|
||||
let histories = tag.history?[0 ... 2].compactMap { history -> History in
|
||||
History.insert(into: self.context.managedObjectContext, property: History.Property(day: history.day, uses: history.uses, accounts: history.accounts))
|
||||
let (tagInCoreData,_) = APIService.CoreData.createOrMergeTag(into: self.context.managedObjectContext, entity: tag)
|
||||
if let searchHistories = searchHistories {
|
||||
let history = searchHistories.first { history -> Bool in
|
||||
guard let hashtag = history.hashtag else { return false }
|
||||
return hashtag.objectID == tagInCoreData.objectID
|
||||
}
|
||||
if let history = history {
|
||||
history.update(updatedAt: Date())
|
||||
} else {
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, hashtag: tagInCoreData)
|
||||
}
|
||||
} else {
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, hashtag: tagInCoreData)
|
||||
}
|
||||
case .accountObjectID(let accountObjectID):
|
||||
if let searchHistories = searchHistories {
|
||||
let history = searchHistories.first { history -> Bool in
|
||||
guard let account = history.account else { return false }
|
||||
return account.objectID == accountObjectID
|
||||
}
|
||||
if let history = history {
|
||||
history.update(updatedAt: Date())
|
||||
}
|
||||
}
|
||||
case .hashtagObjectID(let hashtagObjectID):
|
||||
if let searchHistories = searchHistories {
|
||||
let history = searchHistories.first { history -> Bool in
|
||||
guard let hashtag = history.hashtag else { return false }
|
||||
return hashtag.objectID == hashtagObjectID
|
||||
}
|
||||
if let history = history {
|
||||
history.update(updatedAt: Date())
|
||||
}
|
||||
}
|
||||
let tagInCoreData = Tag.insert(into: self.context.managedObjectContext, property: Tag.Property(name: tag.name, url: tag.url, histories: histories))
|
||||
SearchHistory.insert(into: self.context.managedObjectContext, hashtag: tagInCoreData)
|
||||
|
||||
default:
|
||||
break
|
||||
}
|
||||
|
|
|
@ -96,7 +96,7 @@ extension SearchingTableViewCell {
|
|||
_subTitleLabel.text = ""
|
||||
return
|
||||
}
|
||||
let recentHistory = historys[0 ... 2]
|
||||
let recentHistory = historys.prefix(2)
|
||||
let peopleAreTalking = recentHistory.compactMap { Int($0.accounts) }.reduce(0, +)
|
||||
let string = L10n.Scene.Search.Recommend.HashTag.peopleTalking(String(peopleAreTalking))
|
||||
_subTitleLabel.text = string
|
||||
|
@ -112,7 +112,7 @@ extension SearchingTableViewCell {
|
|||
_subTitleLabel.text = ""
|
||||
return
|
||||
}
|
||||
let recentHistory = historys[0 ... 2]
|
||||
let recentHistory = historys.prefix(2)
|
||||
let peopleAreTalking = recentHistory.compactMap { Int($0.accounts) }.reduce(0, +)
|
||||
let string = L10n.Scene.Search.Recommend.HashTag.peopleTalking(String(peopleAreTalking))
|
||||
_subTitleLabel.text = string
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
//
|
||||
// APIService+CoreData+Tag.swift
|
||||
// Mastodon
|
||||
//
|
||||
// Created by sxiaojian on 2021/4/8.
|
||||
//
|
||||
|
||||
import CoreData
|
||||
import CoreDataStack
|
||||
import Foundation
|
||||
import MastodonSDK
|
||||
|
||||
extension APIService.CoreData {
|
||||
static func createOrMergeTag(
|
||||
into managedObjectContext: NSManagedObjectContext,
|
||||
entity: Mastodon.Entity.Tag
|
||||
) -> (Tag: Tag, isCreated: Bool) {
|
||||
// fetch old mastodon user
|
||||
let oldTag: Tag? = {
|
||||
let request = Tag.sortedFetchRequest
|
||||
request.predicate = Tag.predicate(name: entity.name)
|
||||
request.fetchLimit = 1
|
||||
request.returnsObjectsAsFaults = false
|
||||
do {
|
||||
return try managedObjectContext.fetch(request).first
|
||||
} catch {
|
||||
assertionFailure(error.localizedDescription)
|
||||
return nil
|
||||
}
|
||||
}()
|
||||
|
||||
if let oldTag = oldTag {
|
||||
APIService.CoreData.merge(tag: oldTag, entity: entity, into: managedObjectContext)
|
||||
return (oldTag, false)
|
||||
} else {
|
||||
let histories = entity.history?.prefix(2).compactMap { history -> History in
|
||||
History.insert(into: managedObjectContext, property: History.Property(day: history.day, uses: history.uses, accounts: history.accounts))
|
||||
}
|
||||
let tagInCoreData = Tag.insert(into: managedObjectContext, property: Tag.Property(name: entity.name, url: entity.url, histories: histories))
|
||||
return (tagInCoreData, true)
|
||||
}
|
||||
}
|
||||
|
||||
static func merge(tag:Tag,entity:Mastodon.Entity.Tag,into managedObjectContext: NSManagedObjectContext) {
|
||||
tag.update(url: tag.url)
|
||||
guard let tagHistories = tag.histories else { return }
|
||||
guard let entityHistories = entity.history?.prefix(2) else { return }
|
||||
let entityHistoriesCount = entityHistories.count
|
||||
if entityHistoriesCount == 0 {
|
||||
return
|
||||
}
|
||||
for n in 0..<tagHistories.count {
|
||||
if n < entityHistories.count {
|
||||
let entityHistory = entityHistories[n]
|
||||
tag.updateHistory(index: n, day: entityHistory.day, uses: entityHistory.uses, account: entityHistory.accounts)
|
||||
}
|
||||
}
|
||||
if entityHistoriesCount <= tagHistories.count {
|
||||
return
|
||||
}
|
||||
for n in 1...(entityHistoriesCount - tagHistories.count) {
|
||||
let entityHistory = entityHistories[entityHistoriesCount - n]
|
||||
tag.appendHistory(history: History.insert(into: managedObjectContext, property: History.Property(day: entityHistory.day, uses: entityHistory.uses, accounts: entityHistory.accounts)))
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue