diff --git a/ClientKit/Sources/ClientKit/Extensions/Status+MediaAttachmentType.swift b/ClientKit/Sources/ClientKit/Extensions/Status+MediaAttachmentType.swift
index 7cce704..76b6c53 100644
--- a/ClientKit/Sources/ClientKit/Extensions/Status+MediaAttachmentType.swift
+++ b/ClientKit/Sources/ClientKit/Extensions/Status+MediaAttachmentType.swift
@@ -19,6 +19,11 @@ public extension Status {
func statusContainsImage() -> Bool {
return getAllImageMediaAttachments().isEmpty == false
}
+
+ func statusContainsAltText() -> Bool {
+ let mediaAttachments = self.getAllImageMediaAttachments()
+ return mediaAttachments.contains(where: { $0.description?.isEmpty == false })
+ }
func getAllImageMediaAttachments() -> [MediaAttachment] {
if let reblog = self.reblog {
diff --git a/CoreData/ApplicationSettings+CoreDataProperties.swift b/CoreData/ApplicationSettings+CoreDataProperties.swift
index 1c9a977..77de39e 100644
--- a/CoreData/ApplicationSettings+CoreDataProperties.swift
+++ b/CoreData/ApplicationSettings+CoreDataProperties.swift
@@ -35,6 +35,7 @@ extension ApplicationSettings {
@NSManaged public var warnAboutMissingAlt: Bool
@NSManaged public var showGridOnUserProfile: Bool
@NSManaged public var showReboostedStatuses: Bool
+ @NSManaged public var hideStatusesWithoutAlt: Bool
@NSManaged public var customNavigationMenuItem1: Int32
@NSManaged public var customNavigationMenuItem2: Int32
diff --git a/CoreData/ApplicationSettingsHandler.swift b/CoreData/ApplicationSettingsHandler.swift
index a2e5541..e23a3da 100644
--- a/CoreData/ApplicationSettingsHandler.swift
+++ b/CoreData/ApplicationSettingsHandler.swift
@@ -60,6 +60,7 @@ class ApplicationSettingsHandler {
applicationState.warnAboutMissingAlt = defaultSettings.warnAboutMissingAlt
applicationState.showGridOnUserProfile = defaultSettings.showGridOnUserProfile
applicationState.showReboostedStatuses = defaultSettings.showReboostedStatuses
+ applicationState.hideStatusesWithoutAlt = defaultSettings.hideStatusesWithoutAlt
if let menuPosition = MenuPosition(rawValue: Int(defaultSettings.menuPosition)) {
applicationState.menuPosition = menuPosition
@@ -204,6 +205,12 @@ class ApplicationSettingsHandler {
CoreDataHandler.shared.save()
}
+ func set(hideStatusesWithoutAlt: Bool) {
+ let defaultSettings = self.get()
+ defaultSettings.hideStatusesWithoutAlt = hideStatusesWithoutAlt
+ CoreDataHandler.shared.save()
+ }
+
private func createApplicationSettingsEntity(viewContext: NSManagedObjectContext? = nil) -> ApplicationSettings {
let context = viewContext ?? CoreDataHandler.shared.container.viewContext
return ApplicationSettings(context: context)
diff --git a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
index 3adfca2..91b43ba 100644
--- a/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
+++ b/CoreData/Vernissage.xcdatamodeld/.xccurrentversion
@@ -3,6 +3,6 @@
_XCCurrentVersionName
- Vernissage-018.xcdatamodel
+ Vernissage-019.xcdatamodel
diff --git a/CoreData/Vernissage.xcdatamodeld/Vernissage-019.xcdatamodel/contents b/CoreData/Vernissage.xcdatamodeld/Vernissage-019.xcdatamodel/contents
new file mode 100644
index 0000000..51a0c56
--- /dev/null
+++ b/CoreData/Vernissage.xcdatamodeld/Vernissage-019.xcdatamodel/contents
@@ -0,0 +1,118 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/EnvironmentKit/Sources/EnvironmentKit/ApplicationState.swift b/EnvironmentKit/Sources/EnvironmentKit/ApplicationState.swift
index 9049cef..40fd57e 100644
--- a/EnvironmentKit/Sources/EnvironmentKit/ApplicationState.swift
+++ b/EnvironmentKit/Sources/EnvironmentKit/ApplicationState.swift
@@ -109,6 +109,9 @@ public class ApplicationState: ObservableObject {
/// Show reboosted statuses on home timeline.
@Published public var showReboostedStatuses = false
+
+ /// Hide statuses without ALT text.
+ @Published public var hideStatusesWithoutAlt = false
public func changeApplicationState(accountModel: AccountModel, instance: Instance?, lastSeenStatusId: String?) {
self.account = accountModel
diff --git a/Localization/en.lproj/Localizable.strings b/Localization/en.lproj/Localizable.strings
index fc47004..283404a 100644
--- a/Localization/en.lproj/Localizable.strings
+++ b/Localization/en.lproj/Localizable.strings
@@ -130,6 +130,7 @@
"userProfile.title.blocked" = "Blocked";
"userProfile.title.enableBoosts" = "Enable boosts";
"userProfile.title.disableBoosts" = "Disable boosts";
+"userProfile.title.boostedStatusesMuted" = "Boosts muted";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Notifications";
@@ -244,6 +245,8 @@
"settings.title.warnAboutMissingAltDescription" = "A warning about missing ALT texts will be displayed before publishing new post.";
"settings.title.enableReboostOnTimeline" = "Show boosted statuses";
"settings.title.enableReboostOnTimelineDescription" = "Boosted statuses will be visible on your home timeline.";
+"settings.title.hideStatusesWithoutAlt" = "Hide statuses without ALT text";
+"settings.title.hideStatusesWithoutAltDescription" = "Statuses without ALT text will not be visible on your home timeline.";
// Mark: Signin view.
"signin.navigationBar.title" = "Sign in to Pixelfed";
diff --git a/Localization/eu.lproj/Localizable.strings b/Localization/eu.lproj/Localizable.strings
index a66ce04..b2fa49c 100644
--- a/Localization/eu.lproj/Localizable.strings
+++ b/Localization/eu.lproj/Localizable.strings
@@ -130,6 +130,7 @@
"userProfile.title.blocked" = "Blokeatuta";
"userProfile.title.enableBoosts" = "Enable boosts";
"userProfile.title.disableBoosts" = "Disable boosts";
+"userProfile.title.boostedStatusesMuted" = "Boosts muted";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Jakinarazpenak";
@@ -244,6 +245,8 @@
"settings.title.warnAboutMissingAltDescription" = "Irudiren batek deskribapenik ez badu, argitaratu baino lehen abisua erakutsiko da.";
"settings.title.enableReboostOnTimeline" = "Erakutsi bultzatutako egoerak";
"settings.title.enableReboostOnTimelineDescription" = "Besteek bultzatu dituzten egoerak zure denbora-lerroan erakutsiko dira.";
+"settings.title.hideStatusesWithoutAlt" = "Hide statuses without ALT text";
+"settings.title.hideStatusesWithoutAltDescription" = "Statuses without ALT text will not be visible on your home timeline.";
// Mark: Signin view.
"signin.navigationBar.title" = "Hasi saioa Pixelfed-en";
diff --git a/Localization/fr.lproj/Localizable.strings b/Localization/fr.lproj/Localizable.strings
index 64be7f7..fb6b47e 100644
--- a/Localization/fr.lproj/Localizable.strings
+++ b/Localization/fr.lproj/Localizable.strings
@@ -130,6 +130,7 @@
"userProfile.title.blocked" = "Bloquer";
"userProfile.title.enableBoosts" = "Enable boosts";
"userProfile.title.disableBoosts" = "Disable boosts";
+"userProfile.title.boostedStatusesMuted" = "Boosts muted";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Notifications";
@@ -244,6 +245,8 @@
"settings.title.warnAboutMissingAltDescription" = "Un avertissement concernant les textes ALT manquants sera affiché avant la publication d'un nouveau message.";
"settings.title.enableReboostOnTimeline" = "Show boosted statuses";
"settings.title.enableReboostOnTimelineDescription" = "Boosted statuses will be visible on your home timeline.";
+"settings.title.hideStatusesWithoutAlt" = "Hide statuses without ALT text";
+"settings.title.hideStatusesWithoutAltDescription" = "Statuses without ALT text will not be visible on your home timeline.";
// Mark: Signin view.
"signin.navigationBar.title" = "Se connecter à Pixelfed";
diff --git a/Localization/pl.lproj/Localizable.strings b/Localization/pl.lproj/Localizable.strings
index e427bff..488ffce 100644
--- a/Localization/pl.lproj/Localizable.strings
+++ b/Localization/pl.lproj/Localizable.strings
@@ -130,6 +130,7 @@
"userProfile.title.blocked" = "Zablokowany";
"userProfile.title.enableBoosts" = "Wyświetl podbicia";
"userProfile.title.disableBoosts" = "Ukryj podbicia";
+"userProfile.title.boostedStatusesMuted" = "Podbicia ukryte";
// Mark: Notifications view.
"notifications.navigationBar.title" = "Powiadomienia";
@@ -244,6 +245,8 @@
"settings.title.warnAboutMissingAltDescription" = "Ostrzeżenie o brakujących tekstach ALT będzie wyświetlane przed opublikowaniem nowego statusu.";
"settings.title.enableReboostOnTimeline" = "Wyświetl podbite statusy";
"settings.title.enableReboostOnTimelineDescription" = "Podbite statusy będą widoczne na twojej osi czasu.";
+"settings.title.hideStatusesWithoutAlt" = "Ukryj statusy bez tekstu ALT";
+"settings.title.hideStatusesWithoutAltDescription" = "Statusy bez tekstu ALT nie będą wyświetlane na twojej osi czasu.";
// Mark: Signin view.
"signin.navigationBar.title" = "Zaloguj się do Pixelfed";
diff --git a/Vernissage.xcodeproj/project.pbxproj b/Vernissage.xcodeproj/project.pbxproj
index 01c90ed..148e560 100644
--- a/Vernissage.xcodeproj/project.pbxproj
+++ b/Vernissage.xcodeproj/project.pbxproj
@@ -344,6 +344,7 @@
F870EE5129F1645C00A2D43B /* MainNavigationOptions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainNavigationOptions.swift; sourceTree = ""; };
F871F21C29EF0D7000A351EF /* NavigationMenuItemDetails.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavigationMenuItemDetails.swift; sourceTree = ""; };
F871F21F29EF0FEC00A351EF /* Vernissage-011.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-011.xcdatamodel"; sourceTree = ""; };
+ F87425F62AD5402700A119D7 /* Vernissage-019.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Vernissage-019.xcdatamodel"; sourceTree = ""; };
F8742FC329990AFB00E9642B /* ClientError.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ClientError.swift; sourceTree = ""; };
F8764186298ABB520057D362 /* ViewState.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewState.swift; sourceTree = ""; };
F876418C298AE5020057D362 /* PaginableStatusesView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PaginableStatusesView.swift; sourceTree = ""; };
@@ -1373,7 +1374,7 @@
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@@ -1404,7 +1405,7 @@
ASSETCATALOG_COMPILER_WIDGET_BACKGROUND_COLOR_NAME = WidgetBackground;
CODE_SIGN_ENTITLEMENTS = VernissageWidget/VernissageWidgetExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageWidget/Info.plist;
@@ -1434,7 +1435,7 @@
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageShare/Info.plist;
@@ -1463,7 +1464,7 @@
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = NO;
CODE_SIGN_ENTITLEMENTS = VernissageShare/VernissageShareExtension.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_TEAM = B2U9FEKYP8;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = VernissageShare/Info.plist;
@@ -1617,7 +1618,7 @@
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@@ -1660,7 +1661,7 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
CODE_SIGN_ENTITLEMENTS = Vernissage/Vernissage.entitlements;
CODE_SIGN_STYLE = Automatic;
- CURRENT_PROJECT_VERSION = 302;
+ CURRENT_PROJECT_VERSION = 304;
DEVELOPMENT_ASSET_PATHS = "\"Vernissage/Preview Content\"";
DEVELOPMENT_TEAM = B2U9FEKYP8;
ENABLE_PREVIEWS = YES;
@@ -1857,6 +1858,7 @@
F88C2476295C37BB0006098B /* Vernissage.xcdatamodeld */ = {
isa = XCVersionGroup;
children = (
+ F87425F62AD5402700A119D7 /* Vernissage-019.xcdatamodel */,
F8E7ADF82AD44AFD0038FFFD /* Vernissage-018.xcdatamodel */,
F8D8E0D22ACC89CB00AA1374 /* Vernissage-017.xcdatamodel */,
F8BD04192ACC2280004B8E2C /* Vernissage-016.xcdatamodel */,
@@ -1877,7 +1879,7 @@
F8C937A929882CA90004D782 /* Vernissage-001.xcdatamodel */,
F88C2477295C37BB0006098B /* Vernissage.xcdatamodel */,
);
- currentVersion = F8E7ADF82AD44AFD0038FFFD /* Vernissage-018.xcdatamodel */;
+ currentVersion = F87425F62AD5402700A119D7 /* Vernissage-019.xcdatamodel */;
path = Vernissage.xcdatamodeld;
sourceTree = "";
versionGroupType = wrapper.xcdatamodel;
diff --git a/Vernissage/Services/HomeTimelineService.swift b/Vernissage/Services/HomeTimelineService.swift
index 1a3c057..ecdd45b 100644
--- a/Vernissage/Services/HomeTimelineService.swift
+++ b/Vernissage/Services/HomeTimelineService.swift
@@ -24,7 +24,7 @@ public class HomeTimelineService {
private let semaphore = AsyncSemaphore(value: 1)
@MainActor
- public func loadOnBottom(for account: AccountModel, includeReblogs: Bool) async throws -> Int {
+ public func loadOnBottom(for account: AccountModel, includeReblogs: Bool, hideStatusesWithoutAlt: Bool) async throws -> Int {
// Load data from API and operate on CoreData on background context.
let backgroundContext = CoreDataHandler.shared.newBackgroundContext()
@@ -36,7 +36,11 @@ public class HomeTimelineService {
}
// Load data on bottom of the list.
- let allStatusesFromApi = try await self.load(for: account, includeReblogs: includeReblogs, on: backgroundContext, maxId: oldestStatus.id)
+ let allStatusesFromApi = try await self.load(for: account,
+ includeReblogs: includeReblogs,
+ hideStatusesWithoutAlt: hideStatusesWithoutAlt,
+ on: backgroundContext,
+ maxId: oldestStatus.id)
// Save data into database.
CoreDataHandler.shared.save(viewContext: backgroundContext)
@@ -49,7 +53,7 @@ public class HomeTimelineService {
}
@MainActor
- public func refreshTimeline(for account: AccountModel, includeReblogs: Bool, updateLastSeenStatus: Bool = false) async throws -> String? {
+ public func refreshTimeline(for account: AccountModel, includeReblogs: Bool, hideStatusesWithoutAlt: Bool, updateLastSeenStatus: Bool = false) async throws -> String? {
await semaphore.wait()
defer { semaphore.signal() }
@@ -62,7 +66,10 @@ public class HomeTimelineService {
// Refresh/load home timeline (refreshing on top downloads always first 40 items).
// When Apple introduce good way to show new items without scroll to top then we can change that method.
- let allStatusesFromApi = try await self.refresh(for: account, includeReblogs: includeReblogs, on: backgroundContext)
+ let allStatusesFromApi = try await self.refresh(for: account,
+ includeReblogs: includeReblogs,
+ hideStatusesWithoutAlt: hideStatusesWithoutAlt,
+ on: backgroundContext)
// Update last seen status.
if let lastSeenStatusId, updateLastSeenStatus == true {
@@ -95,7 +102,7 @@ public class HomeTimelineService {
CoreDataHandler.shared.save()
}
- public func amountOfNewStatuses(for account: AccountModel, includeReblogs: Bool) async -> Int {
+ public func amountOfNewStatuses(for account: AccountModel, includeReblogs: Bool, hideStatusesWithoutAlt: Bool) async -> Int {
await semaphore.wait()
defer { semaphore.signal() }
@@ -131,6 +138,11 @@ public class HomeTimelineService {
let statusesWithImagesOnly = downloadedStatuses.getStatusesWithImagesOnly()
for status in statusesWithImagesOnly {
+ // We have to hide statuses without ALT text.
+ if hideStatusesWithoutAlt && status.statusContainsAltText() == false {
+ continue
+ }
+
// We shouldn't add statuses that are boosted by muted accounts.
if AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: account.id, status: status, viewContext: backgroundContext) {
continue
@@ -190,9 +202,12 @@ public class HomeTimelineService {
return statusData
}
- private func refresh(for account: AccountModel, includeReblogs: Bool, on backgroundContext: NSManagedObjectContext) async throws -> [Status] {
+ private func refresh(for account: AccountModel, includeReblogs: Bool, hideStatusesWithoutAlt: Bool, on backgroundContext: NSManagedObjectContext) async throws -> [Status] {
// Retrieve statuses from API.
- let statuses = try await self.getUniqueStatusesForHomeTimeline(account: account, includeReblogs: includeReblogs, on: backgroundContext)
+ let statuses = try await self.getUniqueStatusesForHomeTimeline(account: account,
+ includeReblogs: includeReblogs,
+ hideStatusesWithoutAlt: hideStatusesWithoutAlt,
+ on: backgroundContext)
// Update all existing statuses in database.
for status in statuses {
@@ -246,11 +261,16 @@ public class HomeTimelineService {
private func load(for account: AccountModel,
includeReblogs: Bool,
+ hideStatusesWithoutAlt: Bool,
on backgroundContext: NSManagedObjectContext,
maxId: String? = nil
) async throws -> [Status] {
// Retrieve statuses from API.
- let statuses = try await self.getUniqueStatusesForHomeTimeline(account: account, maxId: maxId, includeReblogs: includeReblogs, on: backgroundContext)
+ let statuses = try await self.getUniqueStatusesForHomeTimeline(account: account,
+ maxId: maxId,
+ includeReblogs: includeReblogs,
+ hideStatusesWithoutAlt: hideStatusesWithoutAlt,
+ on: backgroundContext)
// Save statuses in database.
try await self.add(statuses, for: account, on: backgroundContext)
@@ -348,7 +368,11 @@ public class HomeTimelineService {
return ViewedStatusHandler.shared.hasBeenAlreadyOnTimeline(accountId: accountId, status: status, viewContext: backgroundContext)
}
- private func getUniqueStatusesForHomeTimeline(account: AccountModel, maxId: EntityId? = nil, includeReblogs: Bool? = nil, on backgroundContext: NSManagedObjectContext) async throws -> [Status] {
+ private func getUniqueStatusesForHomeTimeline(account: AccountModel,
+ maxId: EntityId? = nil,
+ includeReblogs: Bool? = nil,
+ hideStatusesWithoutAlt: Bool = false,
+ on backgroundContext: NSManagedObjectContext) async throws -> [Status] {
guard let accessToken = account.accessToken else {
return []
}
@@ -371,6 +395,11 @@ public class HomeTimelineService {
let statusesWithImagesOnly = downloadedStatuses.getStatusesWithImagesOnly()
for status in statusesWithImagesOnly {
+ // We have to hide statuses without ALT text.
+ if hideStatusesWithoutAlt && status.statusContainsAltText() == false {
+ continue
+ }
+
// We shouldn't add statuses that are boosted by muted accounts.
if AccountRelationshipHandler.shared.isBoostedStatusesMuted(accountId: account.id, status: status, viewContext: backgroundContext) {
continue
diff --git a/Vernissage/VernissageApp.swift b/Vernissage/VernissageApp.swift
index 75a7d49..4517ea8 100644
--- a/Vernissage/VernissageApp.swift
+++ b/Vernissage/VernissageApp.swift
@@ -205,7 +205,8 @@ struct VernissageApp: App {
private func calculateNewPhotosInBackground() async {
if let account = self.applicationState.account {
self.applicationState.amountOfNewStatuses = await HomeTimelineService.shared.amountOfNewStatuses(for: account,
- includeReblogs: self.applicationState.showReboostedStatuses)
+ includeReblogs: self.applicationState.showReboostedStatuses,
+ hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt)
}
}
}
diff --git a/Vernissage/Views/HomeFeedView.swift b/Vernissage/Views/HomeFeedView.swift
index beaf707..9ce2d74 100644
--- a/Vernissage/Views/HomeFeedView.swift
+++ b/Vernissage/Views/HomeFeedView.swift
@@ -71,7 +71,12 @@ struct HomeFeedView: View {
.task {
do {
if let account = self.applicationState.account {
- let newStatusesCount = try await HomeTimelineService.shared.loadOnBottom(for: account, includeReblogs: self.applicationState.showReboostedStatuses)
+ let newStatusesCount = try await HomeTimelineService.shared.loadOnBottom(
+ for: account,
+ includeReblogs: self.applicationState.showReboostedStatuses,
+ hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt
+ )
+
if newStatusesCount == 0 {
allItemsLoaded = true
}
@@ -103,7 +108,10 @@ struct HomeFeedView: View {
private func refreshData() async {
do {
if let account = self.applicationState.account {
- let lastSeenStatusId = try await HomeTimelineService.shared.refreshTimeline(for: account, includeReblogs: self.applicationState.showReboostedStatuses, updateLastSeenStatus: true)
+ let lastSeenStatusId = try await HomeTimelineService.shared.refreshTimeline(for: account,
+ includeReblogs: self.applicationState.showReboostedStatuses,
+ hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt,
+ updateLastSeenStatus: true)
asyncAfter(0.75) {
self.applicationState.lastSeenStatusId = lastSeenStatusId
self.applicationState.amountOfNewStatuses = 0
@@ -126,7 +134,9 @@ struct HomeFeedView: View {
}
if let account = self.applicationState.account {
- _ = try await HomeTimelineService.shared.refreshTimeline(for: account, includeReblogs: self.applicationState.showReboostedStatuses)
+ _ = try await HomeTimelineService.shared.refreshTimeline(for: account,
+ includeReblogs: self.applicationState.showReboostedStatuses,
+ hideStatusesWithoutAlt: self.applicationState.hideStatusesWithoutAlt)
}
self.applicationState.amountOfNewStatuses = 0
diff --git a/Vernissage/Views/SettingsView/Subviews/MediaSettingsView.swift b/Vernissage/Views/SettingsView/Subviews/MediaSettingsView.swift
index 8fb41dc..a777f04 100644
--- a/Vernissage/Views/SettingsView/Subviews/MediaSettingsView.swift
+++ b/Vernissage/Views/SettingsView/Subviews/MediaSettingsView.swift
@@ -97,6 +97,18 @@ struct MediaSettingsView: View {
.onChange(of: self.applicationState.showReboostedStatuses) { newValue in
ApplicationSettingsHandler.shared.set(showReboostedStatuses: newValue)
}
+
+ Toggle(isOn: $applicationState.hideStatusesWithoutAlt) {
+ VStack(alignment: .leading) {
+ Text("settings.title.hideStatusesWithoutAlt", comment: "Hide statuses without ALT")
+ Text("settings.title.hideStatusesWithoutAltDescription", comment: "Statuses without ALT text will not be visible on your home timeline.")
+ .font(.footnote)
+ .foregroundColor(.customGrayColor)
+ }
+ }
+ .onChange(of: self.applicationState.hideStatusesWithoutAlt) { newValue in
+ ApplicationSettingsHandler.shared.set(hideStatusesWithoutAlt: newValue)
+ }
}
}
}
diff --git a/Vernissage/Views/StatusesView.swift b/Vernissage/Views/StatusesView.swift
index 51bb99f..4d82f12 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 hide statuses without ALT text.
+ if self.shouldHideStatusWithoutAlt(status: item) {
+ continue
+ }
+
// 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
@@ -217,6 +222,11 @@ struct StatusesView: View {
// Get only statuses with images.
var inPlaceStatuses: [StatusModel] = []
for item in previousStatuses.getStatusesWithImagesOnly() {
+ // We have to hide statuses without ALT text.
+ if self.shouldHideStatusWithoutAlt(status: item) {
+ continue
+ }
+
// 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
@@ -247,6 +257,11 @@ struct StatusesView: View {
// Get only statuses with images.
var inPlaceStatuses: [StatusModel] = []
for item in statuses.getStatusesWithImagesOnly() {
+ // We have to hide statuses without ALT text.
+ if self.shouldHideStatusWithoutAlt(status: item) {
+ continue
+ }
+
// 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
@@ -366,4 +381,16 @@ struct StatusesView: View {
private func prefetch(statusModels: [StatusModel]) {
imagePrefetcher.startPrefetching(with: statusModels.getAllImagesUrls())
}
+
+ private func shouldHideStatusWithoutAlt(status: Status) -> Bool {
+ if self.applicationState.hideStatusesWithoutAlt == false {
+ return false
+ }
+
+ if self.listType != .home && self.listType != .local && self.listType != .federated {
+ return false
+ }
+
+ return status.statusContainsAltText() == false
+ }
}
diff --git a/Vernissage/Views/UserProfileView/Subviews/UserProfileHeaderView.swift b/Vernissage/Views/UserProfileView/Subviews/UserProfileHeaderView.swift
index e5030eb..b81119f 100644
--- a/Vernissage/Views/UserProfileView/Subviews/UserProfileHeaderView.swift
+++ b/Vernissage/Views/UserProfileView/Subviews/UserProfileHeaderView.swift
@@ -18,7 +18,8 @@ struct UserProfileHeaderView: View {
@State var account: Account
@ObservedObject var relationship = RelationshipModel()
-
+ @Binding var boostsDisabled: Bool
+
var body: some View {
VStack(alignment: .leading) {
HStack(alignment: .center) {
@@ -109,7 +110,7 @@ struct UserProfileHeaderView: View {
@ViewBuilder
private func accountRelationshipPanel() -> some View {
- if self.relationship.followedBy || self.relationship.muting || self.relationship.blocking {
+ if self.relationship.followedBy || self.relationship.muting || self.relationship.blocking || self.boostsDisabled {
HStack(alignment: .top) {
if self.relationship.followedBy {
TagWidget(value: "userProfile.title.followsYou", color: .secondary, systemImage: "person.crop.circle.badge.checkmark")
@@ -118,13 +119,18 @@ struct UserProfileHeaderView: View {
if self.relationship.muting {
TagWidget(value: "userProfile.title.muted", color: .accentColor, systemImage: "message.and.waveform.fill")
}
+
+ if self.boostsDisabled {
+ TagWidget(value: "userProfile.title.boostedStatusesMuted", color: .accentColor, image: "custom.rocket.fill")
+ }
if self.relationship.blocking {
TagWidget(value: "userProfile.title.blocked", color: .dangerColor, systemImage: "hand.raised.fill")
}
-
+
Spacer()
}
+ .transition(.opacity)
}
}
diff --git a/Vernissage/Views/UserProfileView/UserProfileView.swift b/Vernissage/Views/UserProfileView/UserProfileView.swift
index 8587a2a..e11dd58 100644
--- a/Vernissage/Views/UserProfileView/UserProfileView.swift
+++ b/Vernissage/Views/UserProfileView/UserProfileView.swift
@@ -70,7 +70,7 @@ struct UserProfileView: View {
private func accountView(account: Account) -> some View {
ScrollView {
- UserProfileHeaderView(account: account, relationship: relationship)
+ UserProfileHeaderView(account: account, relationship: relationship, boostsDisabled: $boostsDisabled)
.id(self.viewId)
if self.applicationState.account?.id == account.id || self.relationship.haveAccessToPhotos(account: account) {
diff --git a/WidgetsKit/Sources/WidgetsKit/Widgets/TagWidget.swift b/WidgetsKit/Sources/WidgetsKit/Widgets/TagWidget.swift
index 0f33276..da1aefc 100644
--- a/WidgetsKit/Sources/WidgetsKit/Widgets/TagWidget.swift
+++ b/WidgetsKit/Sources/WidgetsKit/Widgets/TagWidget.swift
@@ -10,11 +10,13 @@ public struct TagWidget: View {
private let value: LocalizedStringKey
private let color: Color
private let systemImage: String?
+ private let image: String?
- public init(value: LocalizedStringKey, color: Color, systemImage: String? = nil) {
+ public init(value: LocalizedStringKey, color: Color, systemImage: String? = nil, image: String? = nil) {
self.value = value
self.color = color
self.systemImage = systemImage
+ self.image = image
}
public var body: some View {
@@ -24,6 +26,12 @@ public struct TagWidget: View {
.foregroundColor(.white)
.font(.footnote)
}
+
+ if let image {
+ Image(image)
+ .foregroundColor(.white)
+ .font(.footnote)
+ }
Text(self.value, comment: "value")
.foregroundColor(.white)