diff --git a/CoreData/AccountData+CoreDataProperties.swift b/CoreData/AccountData+CoreDataProperties.swift index e7252d2..786ba89 100644 --- a/CoreData/AccountData+CoreDataProperties.swift +++ b/CoreData/AccountData+CoreDataProperties.swift @@ -35,6 +35,7 @@ extension AccountData { @NSManaged public var username: String @NSManaged public var statuses: Set? @NSManaged public var viewedStatuses: Set? + @NSManaged public var accountRelationships: Set? @NSManaged public var lastSeenStatusId: String? } @@ -64,6 +65,19 @@ extension AccountData { @objc(removeViewedStatuses:) @NSManaged public func removeFromViewedStatuses(_ values: NSSet) + + + @objc(addAccountRelationshipsObject:) + @NSManaged public func addToAccountRelationships(_ value: AccountRelationship) + + @objc(removeAccountRelationshipsObject:) + @NSManaged public func removeFromVAccountRelationships(_ value: AccountRelationship) + + @objc(addAccountRelationships:) + @NSManaged public func addToAccountRelationships(_ values: NSSet) + + @objc(removeAccountRelationships:) + @NSManaged public func removeFromAccountRelationships(_ values: NSSet) } extension AccountData: Identifiable { diff --git a/CoreData/AccountRelationship+CoreDataClass.swift b/CoreData/AccountRelationship+CoreDataClass.swift new file mode 100644 index 0000000..44e7890 --- /dev/null +++ b/CoreData/AccountRelationship+CoreDataClass.swift @@ -0,0 +1,12 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import Foundation +import CoreData + +@objc(AccountRelationship) +public class AccountRelationship: NSManagedObject { +} diff --git a/CoreData/AccountRelationship+CoreDataProperties.swift b/CoreData/AccountRelationship+CoreDataProperties.swift new file mode 100644 index 0000000..330cea3 --- /dev/null +++ b/CoreData/AccountRelationship+CoreDataProperties.swift @@ -0,0 +1,22 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import Foundation +import CoreData + +extension AccountRelationship { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "AccountRelationship") + } + + @NSManaged public var accountId: String + @NSManaged public var boostedStatusesMuted: Bool + @NSManaged public var pixelfedAccount: AccountData +} + +extension AccountRelationship: Identifiable { +} diff --git a/CoreData/AccountRelationshipHandler.swift b/CoreData/AccountRelationshipHandler.swift new file mode 100644 index 0000000..537968d --- /dev/null +++ b/CoreData/AccountRelationshipHandler.swift @@ -0,0 +1,72 @@ +// +// https://mczachurski.dev +// Copyright © 2023 Marcin Czachurski and the repository contributors. +// Licensed under the Apache License 2.0. +// + +import Foundation +import CoreData +import PixelfedKit + +class AccountRelationshipHandler { + public static let shared = AccountRelationshipHandler() + private init() { } + + func createAccountRelationshipEntity(viewContext: NSManagedObjectContext? = nil) -> AccountRelationship { + let context = viewContext ?? CoreDataHandler.shared.container.viewContext + return AccountRelationship(context: context) + } + + /// Check if boosted statuses from given account are muted. + func isBoostedStatusesMuted(accountId: String, status: Status, viewContext: NSManagedObjectContext? = nil) -> Bool { + if status.reblog == nil { + return false + } + + let accountRelationship = self.getAccountRelationship(for: accountId, relation: status.account.id, viewContext: viewContext) + return accountRelationship?.boostedStatusesMuted ?? false + } + + func isBoostedStatusesMuted(for accountId: String, relation relationAccountId: String, viewContext: NSManagedObjectContext? = nil) -> Bool { + let accountRelationship = self.getAccountRelationship(for: accountId, relation: relationAccountId, viewContext: viewContext) + return accountRelationship?.boostedStatusesMuted ?? false + } + + func setBoostedStatusesMuted(for accountId: String, relation relationAccountId: String, boostedStatusesMuted: Bool, viewContext: NSManagedObjectContext? = nil) { + let context = viewContext ?? CoreDataHandler.shared.container.viewContext + + var accountRelationship = self.getAccountRelationship(for: accountId, relation: relationAccountId, viewContext: context) + if accountRelationship == nil { + guard let accountDataFromDb = AccountDataHandler.shared.getAccountData(accountId: accountId, viewContext: context) else { + return + } + + let newAccountRelationship = AccountRelationshipHandler.shared.createAccountRelationshipEntity(viewContext: context) + newAccountRelationship.accountId = relationAccountId + newAccountRelationship.pixelfedAccount = accountDataFromDb + accountDataFromDb.addToAccountRelationships(newAccountRelationship) + + accountRelationship = newAccountRelationship + } + + accountRelationship?.boostedStatusesMuted = boostedStatusesMuted + CoreDataHandler.shared.save(viewContext: context) + } + + private func getAccountRelationship(for accountId: String, relation relationAccountId: String, viewContext: NSManagedObjectContext? = nil) -> AccountRelationship? { + let context = viewContext ?? CoreDataHandler.shared.container.viewContext + let fetchRequest = AccountRelationship.fetchRequest() + + fetchRequest.fetchLimit = 1 + let statusAccountIddPredicate = NSPredicate(format: "accountId = %@", relationAccountId) + let accountPredicate = NSPredicate(format: "pixelfedAccount.id = %@", accountId) + fetchRequest.predicate = NSCompoundPredicate.init(type: .and, subpredicates: [statusAccountIddPredicate, accountPredicate]) + + do { + return try context.fetch(fetchRequest).first + } catch { + CoreDataError.shared.handle(error, message: "Error during fetching account relationship (isBoostedMutedForAccount).") + return nil + } + } +} diff --git a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion index 0ea4d11..3adfca2 100644 --- a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion +++ b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - Vernissage-017.xcdatamodel + Vernissage-018.xcdatamodel diff --git a/CoreData/Vernissage.xcdatamodeld/Vernissage-018.xcdatamodel/contents b/CoreData/Vernissage.xcdatamodeld/Vernissage-018.xcdatamodel/contents new file mode 100644 index 0000000..2799b42 --- /dev/null +++ b/CoreData/Vernissage.xcdatamodeld/Vernissage-018.xcdatamodel/contents @@ -0,0 +1,117 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Localization/en.lproj/Localizable.strings b/Localization/en.lproj/Localizable.strings index d404952..fc47004 100644 --- a/Localization/en.lproj/Localizable.strings +++ b/Localization/en.lproj/Localizable.strings @@ -128,6 +128,8 @@ "userProfile.title.edit" = "Edit"; "userProfile.title.muted" = "Muted"; "userProfile.title.blocked" = "Blocked"; +"userProfile.title.enableBoosts" = "Enable boosts"; +"userProfile.title.disableBoosts" = "Disable boosts"; // Mark: Notifications view. "notifications.navigationBar.title" = "Notifications"; diff --git a/Localization/eu.lproj/Localizable.strings b/Localization/eu.lproj/Localizable.strings index ab32f89..a66ce04 100644 --- a/Localization/eu.lproj/Localizable.strings +++ b/Localization/eu.lproj/Localizable.strings @@ -128,6 +128,8 @@ "userProfile.title.edit" = "Editatu"; "userProfile.title.muted" = "Mutututa"; "userProfile.title.blocked" = "Blokeatuta"; +"userProfile.title.enableBoosts" = "Enable boosts"; +"userProfile.title.disableBoosts" = "Disable boosts"; // Mark: Notifications view. "notifications.navigationBar.title" = "Jakinarazpenak"; diff --git a/Localization/fr.lproj/Localizable.strings b/Localization/fr.lproj/Localizable.strings index 472244d..64be7f7 100644 --- a/Localization/fr.lproj/Localizable.strings +++ b/Localization/fr.lproj/Localizable.strings @@ -128,6 +128,8 @@ "userProfile.title.edit" = "Editer"; "userProfile.title.muted" = "Sourdine"; "userProfile.title.blocked" = "Bloquer"; +"userProfile.title.enableBoosts" = "Enable boosts"; +"userProfile.title.disableBoosts" = "Disable boosts"; // Mark: Notifications view. "notifications.navigationBar.title" = "Notifications"; diff --git a/Localization/pl.lproj/Localizable.strings b/Localization/pl.lproj/Localizable.strings index 351a159..e427bff 100644 --- a/Localization/pl.lproj/Localizable.strings +++ b/Localization/pl.lproj/Localizable.strings @@ -128,6 +128,8 @@ "userProfile.title.edit" = "Edytuj"; "userProfile.title.muted" = "Wyciszony"; "userProfile.title.blocked" = "Zablokowany"; +"userProfile.title.enableBoosts" = "Wyświetl podbicia"; +"userProfile.title.disableBoosts" = "Ukryj podbicia"; // Mark: Notifications view. "notifications.navigationBar.title" = "Powiadomienia"; diff --git a/Vernissage.xcodeproj/project.pbxproj b/Vernissage.xcodeproj/project.pbxproj index b917620..01c90ed 100644 --- a/Vernissage.xcodeproj/project.pbxproj +++ b/Vernissage.xcodeproj/project.pbxproj @@ -208,6 +208,15 @@ F8E36E462AB8745300769C55 /* Sizable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E36E452AB8745300769C55 /* Sizable.swift */; }; F8E36E482AB874A500769C55 /* StatusModel+Sizeable.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E36E472AB874A500769C55 /* StatusModel+Sizeable.swift */; }; F8E6D03329CDD52500416CCA /* EditProfileView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E6D03229CDD52500416CCA /* EditProfileView.swift */; }; + F8E7ADFA2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADF92AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift */; }; + F8E7ADFB2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADF92AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift */; }; + F8E7ADFC2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADF92AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift */; }; + F8E7ADFE2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift */; }; + F8E7ADFF2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift */; }; + F8E7AE002AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift */; }; + F8E7AE022AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; }; + F8E7AE032AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; }; + F8E7AE042AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */; }; F8F6E44229BC58F20004795E /* Vernissage.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */; }; F8F6E44C29BCC1F70004795E /* PhotoSmallWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44629BCC0DC0004795E /* PhotoSmallWidgetView.swift */; }; F8F6E44D29BCC1F90004795E /* PhotoMediumWidgetView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F8F6E44829BCC0F00004795E /* PhotoMediumWidgetView.swift */; }; @@ -422,6 +431,10 @@ F8E36E452AB8745300769C55 /* Sizable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Sizable.swift; sourceTree = ""; }; F8E36E472AB874A500769C55 /* StatusModel+Sizeable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "StatusModel+Sizeable.swift"; sourceTree = ""; }; F8E6D03229CDD52500416CCA /* EditProfileView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EditProfileView.swift; sourceTree = ""; }; + F8E7ADF82AD44AFD0038FFFD /* Vernissage-018.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-018.xcdatamodel"; sourceTree = ""; }; + F8E7ADF92AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountRelationship+CoreDataClass.swift"; sourceTree = ""; }; + F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AccountRelationship+CoreDataProperties.swift"; sourceTree = ""; }; + F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountRelationshipHandler.swift; sourceTree = ""; }; F8EF371429C624DA00669F45 /* Vernissage-006.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-006.xcdatamodel"; sourceTree = ""; }; F8EF3C8B29FC3A5F00CBFF7C /* Vernissage-012.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-012.xcdatamodel"; sourceTree = ""; }; F8F6E44329BC5CAA0004795E /* VernissageWidgetExtension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = VernissageWidgetExtension.entitlements; sourceTree = ""; }; @@ -586,12 +599,15 @@ F88BC51C29E0377B00CE6141 /* AccountData+AccountModel.swift */, F8D8E0C62ACC234A00AA1374 /* ViewedStatus+CoreDataClass.swift */, F8D8E0CA2ACC237000AA1374 /* ViewedStatus+CoreDataProperties.swift */, + F8E7ADF92AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift */, + F8E7ADFD2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift */, F88C2474295C37BB0006098B /* CoreDataHandler.swift */, F866F6A229604161002E8F88 /* AccountDataHandler.swift */, F866F6A429604194002E8F88 /* ApplicationSettingsHandler.swift */, F80048072961E6DE00E6868A /* StatusDataHandler.swift */, F80048092961EA1900E6868A /* AttachmentDataHandler.swift */, F8D8E0CE2ACC23B300AA1374 /* ViewedStatusHandler.swift */, + F8E7AE012AD44D600038FFFD /* AccountRelationshipHandler.swift */, F864F7A429BBA01D00B13921 /* CoreDataError.swift */, ); path = CoreData; @@ -1124,12 +1140,14 @@ F8F6E44229BC58F20004795E /* Vernissage.xcdatamodeld in Sources */, F8F6E44C29BCC1F70004795E /* PhotoSmallWidgetView.swift in Sources */, F864F76629BB91B400B13921 /* PhotoWidget.swift in Sources */, + F8E7ADFB2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */, F8F6E44D29BCC1F90004795E /* PhotoMediumWidgetView.swift in Sources */, F815F60C29E49CF20044566B /* Avatar.swift in Sources */, F8F6E44E29BCC1FB0004795E /* PhotoLargeWidgetView.swift in Sources */, F864F76429BB91B400B13921 /* VernissageWidgetBundle.swift in Sources */, F864F77D29BB9A4600B13921 /* AttachmentData+CoreDataClass.swift in Sources */, F8D8E0C82ACC234A00AA1374 /* ViewedStatus+CoreDataClass.swift in Sources */, + F8E7ADFF2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */, F8D8E0CC2ACC237000AA1374 /* ViewedStatus+CoreDataProperties.swift in Sources */, F864F7A629BBA01D00B13921 /* CoreDataError.swift in Sources */, F864F77E29BB9A4900B13921 /* AttachmentData+CoreDataProperties.swift in Sources */, @@ -1145,6 +1163,7 @@ F864F78529BB9A7100B13921 /* ApplicationSettings+CoreDataProperties.swift in Sources */, F84625E929FE2788002D3AF4 /* QRCodeWidget.swift in Sources */, F864F78729BB9A7700B13921 /* AccountData+CoreDataProperties.swift in Sources */, + F8E7AE032AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */, F864F78829BB9A7B00B13921 /* CoreDataHandler.swift in Sources */, F8F6E45129BCE9190004795E /* UIImage+Resize.swift in Sources */, F864F78929BB9A7D00B13921 /* AccountDataHandler.swift in Sources */, @@ -1164,9 +1183,11 @@ buildActionMask = 2147483647; files = ( F88BC54529E072B200CE6141 /* AccountDataHandler.swift in Sources */, + F8E7ADFC2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */, F88BC54729E072B800CE6141 /* AccountData+CoreDataProperties.swift in Sources */, F8D8E0D12ACC23B300AA1374 /* ViewedStatusHandler.swift in Sources */, F88BC54D29E072D600CE6141 /* AttachmentData+CoreDataProperties.swift in Sources */, + F8E7AE002AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */, F88BC54F29E073BC00CE6141 /* AccountData+AccountModel.swift in Sources */, F865B4D32A024AFE008ACDFC /* AttachmentData+Faulty.swift in Sources */, F88BC54629E072B500CE6141 /* CoreDataHandler.swift in Sources */, @@ -1176,6 +1197,7 @@ F88BC54429E072AF00CE6141 /* ApplicationSettingsHandler.swift in Sources */, F8D8E0CD2ACC237000AA1374 /* ViewedStatus+CoreDataProperties.swift in Sources */, F88BC51629E0307F00CE6141 /* NotificationsName.swift in Sources */, + F8E7AE042AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */, F88BC54829E072BC00CE6141 /* AccountData+CoreDataClass.swift in Sources */, F88BC51329E02FD800CE6141 /* ComposeView.swift in Sources */, F88BC54E29E072D900CE6141 /* AttachmentData+CoreDataClass.swift in Sources */, @@ -1247,6 +1269,7 @@ F89D6C4A297196FF001DA3D4 /* ImageViewer.swift in Sources */, F8A93D7E2965FD89001D8331 /* UserProfileView.swift in Sources */, F88C246E295C37B80006098B /* MainView.swift in Sources */, + F8E7ADFA2AD44CC00038FFFD /* AccountRelationship+CoreDataClass.swift in Sources */, F8AFF7C429B25EF40087D083 /* ImagesGrid.swift in Sources */, F88C2478295C37BB0006098B /* Vernissage.xcdatamodeld in Sources */, F8AFF7C129B259150087D083 /* HashtagsView.swift in Sources */, @@ -1292,8 +1315,10 @@ F86B7216296BFFDA00EE59EC /* UserProfileStatusesView.swift in Sources */, F8D8E0CB2ACC237000AA1374 /* ViewedStatus+CoreDataProperties.swift in Sources */, F897978F29684BCB00B22335 /* LoadingView.swift in Sources */, + F8E7ADFE2AD44CEB0038FFFD /* AccountRelationship+CoreDataProperties.swift in Sources */, F89992C9296D6DC7005994BF /* CommentBodyView.swift in Sources */, F866F6A1296040A8002E8F88 /* ApplicationSettings+CoreDataProperties.swift in Sources */, + F8E7AE022AD44D600038FFFD /* AccountRelationshipHandler.swift in Sources */, F86A4303299A9AF500DF7645 /* TipsStore.swift in Sources */, F8DF38E629DDB98A0047F1AA /* SocialsSectionView.swift in Sources */, F88BC53B29E06A5100CE6141 /* ImageContextMenu.swift in Sources */, @@ -1348,7 +1373,7 @@ CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1379,7 +1404,7 @@ ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground; CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageWidget/Info.plist; @@ -1409,7 +1434,7 @@ CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageShare/Info.plist; @@ -1438,7 +1463,7 @@ ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = NO; CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_TEAM = B2U9FEKYP8; GENERATE_INFOPLIST_FILE = YES; INFOPLIST_FILE = VernissageShare/Info.plist; @@ -1592,7 +1617,7 @@ CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; @@ -1635,7 +1660,7 @@ ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements; CODE_SIGN_STYLE = Automatic; - CURRENT_PROJECT_VERSION = 301; + CURRENT_PROJECT_VERSION = 302; DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\""; DEVELOPMENT_TEAM = B2U9FEKYP8; ENABLE_PREVIEWS = YES; @@ -1832,6 +1857,7 @@ F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + F8E7ADF82AD44AFD0038FFFD /* Vernissage-018.xcdatamodel */, F8D8E0D22ACC89CB00AA1374 /* Vernissage-017.xcdatamodel */, F8BD04192ACC2280004B8E2C /* Vernissage-016.xcdatamodel */, F880EECE2AC70A2B00C09C31 /* Vernissage-015.xcdatamodel */, @@ -1851,7 +1877,7 @@ F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */, F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */, ); - currentVersion = F8D8E0D22ACC89CB00AA1374 /* Vernissage-017.xcdatamodel */; + currentVersion = F8E7ADF82AD44AFD0038FFFD /* Vernissage-018.xcdatamodel */; path = Vernissage.xcdatamodeld; sourceTree = ""; versionGroupType = wrapper.xcdatamodel; diff --git a/Vernissage/Services/HomeTimelineService.swift b/Vernissage/Services/HomeTimelineService.swift index cb5e33b..1a3c057 100644 --- a/Vernissage/Services/HomeTimelineService.swift +++ b/Vernissage/Services/HomeTimelineService.swift @@ -131,6 +131,11 @@ public class HomeTimelineService { let statusesWithImagesOnly = downloadedStatuses.getStatusesWithImagesOnly() for status in statusesWithImagesOnly { + // We shouldn't add statuses that are boosted by muted accounts. + if AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: account.id, status: status, viewContext: backgroundContext) { + continue + } + // We should add to timeline only statuses that has not been showned to the user already. guard self.hasBeenAlreadyOnTimeline(accountId: account.id, status: status, on: backgroundContext) == false else { continue @@ -366,6 +371,11 @@ public class HomeTimelineService { let statusesWithImagesOnly = downloadedStatuses.getStatusesWithImagesOnly() for status in statusesWithImagesOnly { + // We shouldn't add statuses that are boosted by muted accounts. + if AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: account.id, status: status, viewContext: backgroundContext) { + continue + } + // We should add to timeline only statuses that has not been showned to the user already. guard self.hasBeenAlreadyOnTimeline(accountId: account.id, status: status, on: backgroundContext) == false else { continue diff --git a/Vernissage/Views/StatusesView.swift b/Vernissage/Views/StatusesView.swift index 29178fe..51bb99f 100644 --- a/Vernissage/Views/StatusesView.swift +++ b/Vernissage/Views/StatusesView.swift @@ -185,6 +185,11 @@ struct StatusesView: View { // Get only statuses with images. var inPlaceStatuses: [StatusModel] = [] for item in statuses.getStatusesWithImagesOnly() { + // We have to skip statuses that are boosted from muted accounts. + if let accountId = self.applicationState.account?.id, AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: accountId, status: item) { + continue + } + inPlaceStatuses.append(StatusModel(status: item)) } @@ -212,6 +217,11 @@ struct StatusesView: View { // Get only statuses with images. var inPlaceStatuses: [StatusModel] = [] for item in previousStatuses.getStatusesWithImagesOnly() { + // We have to skip statuses that are boosted from muted accounts. + if let accountId = self.applicationState.account?.id, AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: accountId, status: item) { + continue + } + inPlaceStatuses.append(StatusModel(status: item)) } @@ -237,6 +247,11 @@ struct StatusesView: View { // Get only statuses with images. var inPlaceStatuses: [StatusModel] = [] for item in statuses.getStatusesWithImagesOnly() { + // We have to skip statuses that are boosted from muted accounts. + if let accountId = self.applicationState.account?.id, AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: accountId, status: item) { + continue + } + inPlaceStatuses.append(StatusModel(status: item)) } diff --git a/Vernissage/Views/UserProfileView/UserProfileView.swift b/Vernissage/Views/UserProfileView/UserProfileView.swift index 8abc548..8587a2a 100644 --- a/Vernissage/Views/UserProfileView/UserProfileView.swift +++ b/Vernissage/Views/UserProfileView/UserProfileView.swift @@ -26,6 +26,7 @@ struct UserProfileView: View { @State private var account: Account? @State private var state: ViewState = .loading @State private var viewId = UUID().uuidString + @State private var boostsDisabled = false // Gallery parameters. @State private var imageColumns = 3 @@ -118,6 +119,10 @@ struct UserProfileView: View { } else { self.relationship.update(relationship: RelationshipModel()) } + + if let signedInAccountId = self.applicationState.account?.id { + self.boostsDisabled = AccountRelationshipHandler.shared.isBoostedStatusesMuted(for: signedInAccountId, relation: self.accountId) + } self.account = accountFromApi @@ -167,6 +172,23 @@ struct UserProfileView: View { Label(NSLocalizedString("userProfile.title.block", comment: "Block"), systemImage: "hand.raised") } } + + Button { + Task { + if let signedInAccoountId = self.applicationState.account?.id { + self.boostsDisabled.toggle() + AccountRelationshipHandler.shared.setBoostedStatusesMuted(for: signedInAccoountId, + relation: self.accountId, + boostedStatusesMuted: self.boostsDisabled) + } + } + } label: { + if self.boostsDisabled == true { + Label(NSLocalizedString("userProfile.title.enableBoosts", comment: "Enable boosts"), image: "custom.rocket.fill") + } else { + Label(NSLocalizedString("userProfile.title.disableBoosts", comment: "Disable boosts"), image: "custom.rocket") + } + } Button { self.routerPath.presentedSheet = .report(objectType: .user, objectId: self.accountId)