Skip to content

Commit

Permalink
Accessible Mark Read Indicator (#1543)
Browse files Browse the repository at this point in the history
  • Loading branch information
EricBAndrews authored Dec 26, 2024
1 parent f673171 commit e50d2cf
Show file tree
Hide file tree
Showing 14 changed files with 198 additions and 11 deletions.
12 changes: 12 additions & 0 deletions Mlem.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,7 @@
B104A6DC2A59BF3C00B3E725 /* NukeUI in Frameworks */ = {isa = PBXBuildFile; productRef = B104A6DB2A59BF3C00B3E725 /* NukeUI */; };
B104A6DE2A59BF3C00B3E725 /* NukeVideo in Frameworks */ = {isa = PBXBuildFile; productRef = B104A6DD2A59BF3C00B3E725 /* NukeVideo */; };
B1B78D642A51D53900F72485 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = B1B78D632A51D53900F72485 /* AppDelegate.swift */; };
CD03742A2D1DBFD2001E85FA /* ReadCheck.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD0374292D1DBFCF001E85FA /* ReadCheck.swift */; };
CD0507732C6AA0C8008B1505 /* FeedSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD0507722C6AA0C8008B1505 /* FeedSelection.swift */; };
CD09BA7F2CB4698E00C93926 /* OledPalette.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD09BA7E2CB4698600C93926 /* OledPalette.swift */; };
CD0E06F72C0E739F00445849 /* PostType+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CD0E06F62C0E739F00445849 /* PostType+Extensions.swift */; };
Expand Down Expand Up @@ -399,6 +400,8 @@
CDBFCB6A2C04EFFE008CD468 /* PostSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBFCB692C04EFFE008CD468 /* PostSettingsView.swift */; };
CDBFCB6C2C054AA7008CD468 /* TilePostView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDBFCB6B2C054AA7008CD468 /* TilePostView.swift */; };
CDC199EA2BE449790077B4F1 /* Interactable1Providing+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC199E92BE449790077B4F1 /* Interactable1Providing+Extensions.swift */; };
CDC44A342D1CBBD30030F01C /* AccessibilitySettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC44A332D1CBBCC0030F01C /* AccessibilitySettingsView.swift */; };
CDC44A362D1CBC280030F01C /* ReadPostIndicator.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDC44A352D1CBC200030F01C /* ReadPostIndicator.swift */; };
CDCA44952C17658000C092B3 /* View+QuickSwipes.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCA44942C17658000C092B3 /* View+QuickSwipes.swift */; };
CDCA44972C17666C00C092B3 /* HapticManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = CDCA44962C17666C00C092B3 /* HapticManager.swift */; };
CDCA449B2C1766CF00C092B3 /* Failure.ahap in Resources */ = {isa = PBXBuildFile; fileRef = CDCA449A2C1766CF00C092B3 /* Failure.ahap */; };
Expand Down Expand Up @@ -739,6 +742,7 @@
AD1B0D362A5F7A260006F554 /* Licenses.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Licenses.swift; sourceTree = "<group>"; };
B104A6E12A5AFC9F00B3E725 /* Mlem.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Mlem.entitlements; sourceTree = "<group>"; };
B1B78D632A51D53900F72485 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
CD0374292D1DBFCF001E85FA /* ReadCheck.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadCheck.swift; sourceTree = "<group>"; };
CD0507722C6AA0C8008B1505 /* FeedSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FeedSelection.swift; sourceTree = "<group>"; };
CD09BA7E2CB4698600C93926 /* OledPalette.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OledPalette.swift; sourceTree = "<group>"; };
CD0E06F62C0E739F00445849 /* PostType+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "PostType+Extensions.swift"; sourceTree = "<group>"; };
Expand Down Expand Up @@ -839,6 +843,8 @@
CDBFCB692C04EFFE008CD468 /* PostSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PostSettingsView.swift; sourceTree = "<group>"; };
CDBFCB6B2C054AA7008CD468 /* TilePostView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TilePostView.swift; sourceTree = "<group>"; };
CDC199E92BE449790077B4F1 /* Interactable1Providing+Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Interactable1Providing+Extensions.swift"; sourceTree = "<group>"; };
CDC44A332D1CBBCC0030F01C /* AccessibilitySettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccessibilitySettingsView.swift; sourceTree = "<group>"; };
CDC44A352D1CBC200030F01C /* ReadPostIndicator.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReadPostIndicator.swift; sourceTree = "<group>"; };
CDCA44942C17658000C092B3 /* View+QuickSwipes.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "View+QuickSwipes.swift"; sourceTree = "<group>"; };
CDCA44962C17666C00C092B3 /* HapticManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HapticManager.swift; sourceTree = "<group>"; };
CDCA449A2C1766CF00C092B3 /* Failure.ahap */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = Failure.ahap; sourceTree = "<group>"; };
Expand Down Expand Up @@ -943,6 +949,7 @@
03134A492BEACF46002662CC /* Settings */ = {
isa = PBXGroup;
children = (
CDC44A332D1CBBCC0030F01C /* AccessibilitySettingsView.swift */,
CD45CB0C2D1880E3008BC729 /* FiltersSettingsView.swift */,
0397D4982C6EA68A002C6CDC /* InteractionBarEditor */,
031E2D5C2BEFCC630003BC45 /* SettingsView.swift */,
Expand Down Expand Up @@ -1550,6 +1557,7 @@
CD4D58A82B86BE4C00B82964 /* Shared */ = {
isa = PBXGroup;
children = (
CD0374292D1DBFCF001E85FA /* ReadCheck.swift */,
CDAA02E42C82236200D75633 /* Palette Components */,
03B431C32C45BA45001A1EB5 /* AccountPickerMenu.swift */,
CD4D58AB2B86BE6100B82964 /* Accounts */,
Expand Down Expand Up @@ -1665,6 +1673,7 @@
CD4D58C62B86DCE500B82964 /* Enums */ = {
isa = PBXGroup;
children = (
CDC44A352D1CBC200030F01C /* ReadPostIndicator.swift */,
CD4D58C72B86DCED00B82964 /* AvatarType.swift */,
03CBD18C2C6120F600E870BC /* PersonFlair.swift */,
03AF91E62C1C65AE00E56644 /* Interaction */,
Expand Down Expand Up @@ -2275,6 +2284,7 @@
03D2A6372C00F92400ED4FF2 /* Session.swift in Sources */,
03AF91DD2C1B23E500E56644 /* ImageViewer.swift in Sources */,
CD13CC592C583C7A001AF428 /* WebsitePreviewView.swift in Sources */,
CDC44A342D1CBBD30030F01C /* AccessibilitySettingsView.swift in Sources */,
CD869FCE2C15F90C00FC8B5B /* ChildSizeReader.swift in Sources */,
035EDEF12C2DE94B00F51144 /* DefaultTextInputType.swift in Sources */,
039F588C2C7B574E00C61658 /* AdvancedSettingsView.swift in Sources */,
Expand Down Expand Up @@ -2522,6 +2532,7 @@
033F84C32C2B12AA002E3EDF /* InstanceSummary.swift in Sources */,
0369B3532BFA514B001EFEDF /* ToastLocation.swift in Sources */,
036ED6792D0AF3740018E5EA /* PinnedSortTracker.swift in Sources */,
CDC44A362D1CBC280030F01C /* ReadPostIndicator.swift in Sources */,
0353948D2CA080EB00795AA5 /* FeedWelcomeView.swift in Sources */,
03049A202C650A8100FF6889 /* FormReadout.swift in Sources */,
030050D32D109B7E002B1E99 /* ReportView.swift in Sources */,
Expand All @@ -2538,6 +2549,7 @@
033FCB282C5E3933007B7CD1 /* AlternateIcon.swift in Sources */,
038028F62CB096960091A8A2 /* SearchView+FilterModels.swift in Sources */,
033FCB292C5E3933007B7CD1 /* IconSettingsView.swift in Sources */,
CD03742A2D1DBFD2001E85FA /* ReadCheck.swift in Sources */,
035394932CA1AE2C00795AA5 /* UptimeData.swift in Sources */,
036ED6832D0C483B0018E5EA /* Profile2Providing+Extensions.swift in Sources */,
033FCB2A2C5E3933007B7CD1 /* AlternateIconCell.swift in Sources */,
Expand Down
12 changes: 6 additions & 6 deletions Mlem/App/Configuration/User Settings/CodableSettings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,8 @@ import UIKit

/// Mirror of Settings but without any AppStorage complexity and fully optionalized.
struct CodableSettings: Codable {
var a11y_markReadType: String // TODO: pending a11y mark read
var a11y_readBarThickness: Int
var a11y_readPostIndicator: ReadPostIndicator
var a11y_readOutlineThickness: Int
var a11y_websiteThumbnailIcon: Bool
var accounts_defaultId: Int?
var accounts_grouped: Bool
Expand Down Expand Up @@ -88,8 +88,8 @@ struct CodableSettings: Codable {
// swiftlint:disable line_length function_body_length
init(from decoder: any Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
self.a11y_markReadType = try container.decodeIfPresent(String.self, forKey: .a11y_markReadType) ?? "bar"
self.a11y_readBarThickness = try container.decodeIfPresent(Int.self, forKey: .a11y_readBarThickness) ?? 3
self.a11y_readPostIndicator = try container.decodeIfPresent(ReadPostIndicator.self, forKey: .a11y_readPostIndicator) ?? .checkmark
self.a11y_readOutlineThickness = try container.decodeIfPresent(Int.self, forKey: .a11y_readOutlineThickness) ?? 3
self.a11y_websiteThumbnailIcon = try container.decodeIfPresent(Bool.self, forKey: .a11y_websiteThumbnailIcon) ?? false
self.accounts_defaultId = try container.decodeIfPresent(Int?.self, forKey: .accounts_defaultId) ?? nil
self.accounts_grouped = try container.decodeIfPresent(Bool.self, forKey: .accounts_grouped) ?? false
Expand Down Expand Up @@ -166,8 +166,8 @@ struct CodableSettings: Codable {
// swiftlint:enable line_length

init(from settings: Settings) {
self.a11y_markReadType = "bar"
self.a11y_readBarThickness = 3
self.a11y_readPostIndicator = .checkmark
self.a11y_readOutlineThickness = 3
self.a11y_websiteThumbnailIcon = false
self.accounts_defaultId = nil
self.accounts_grouped = settings.groupAccountSort
Expand Down
5 changes: 5 additions & 0 deletions Mlem/App/Configuration/User Settings/Settings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Settings: ObservableObject {
/// Default initializer. Will take current AppStorage values.
init() {}

@AppStorage("a11y.readPostIndicator") var readPostIndicator: ReadPostIndicator = .checkmark
@AppStorage("a11y.readOutlineThickness") var readOutlineThickness: Int = 3

@AppStorage("post.size") var postSize: PostSize = .compact
@AppStorage("post.defaultSort") var defaultPostSort: ApiSortType = .hot
@AppStorage("post.fallbackSort") var fallbackPostSort: ApiSortType = .hot
Expand Down Expand Up @@ -152,5 +155,7 @@ class Settings: ObservableObject {
swipeAnywhereToNavigate = settings.navigation_swipeAnywhere
moderatorActionGrouping = settings.menus_modActionGrouping
showAllModActions = settings.menus_allModActions
readPostIndicator = settings.a11y_readPostIndicator
readOutlineThickness = settings.a11y_readOutlineThickness
}
}
20 changes: 20 additions & 0 deletions Mlem/App/Enums/ReadPostIndicator.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
//
// ReadPostIndicator.swift
// Mlem
//
// Created by Eric Andrews on 2024-12-25.
//

import Foundation

enum ReadPostIndicator: String, CaseIterable, Codable {
case outline, checkmark, none

var label: LocalizedStringResource {
switch self {
case .outline: "Outline"
case .checkmark: "Checkmark"
case .none: "None"
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import SwiftUI
struct CompactPostView: View {
@Setting(\.thumbnailLocation) var thumbnailLocation
@Setting(\.blurNsfw) var blurNsfw
@Setting(\.readPostIndicator) var readPostIndicator

@Environment(\.communityContext) var communityContext: (any Community1Providing)?
@Environment(Palette.self) var palette: Palette
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

let post: any Post1Providing

Expand Down Expand Up @@ -52,6 +54,10 @@ struct CompactPostView: View {
FullyQualifiedLinkView(entity: post.community_, labelStyle: .small, showAvatar: false)
}
Spacer()

if differentiateWithoutColor, readPostIndicator == .checkmark, post.read_ ?? false {
ReadCheck()
}

if post.nsfw {
Image(Icons.nsfwTag)
Expand Down
20 changes: 17 additions & 3 deletions Mlem/App/Views/Root/Tabs/Feeds/Feed Posts/FeedPostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,22 @@ struct FeedPostView<EmbeddedContent: View>: View {
@Environment(NavigationLayer.self) private var navigation
@Environment(Palette.self) private var palette
@Environment(FiltersTracker.self) var filtersTracker
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

@State var obscured: Bool

@Setting(\.postSize) private var postSize
@Setting(\.postSize) private var settingsPostSize
@Setting(\.readPostIndicator) var readPostIndicator
@Setting(\.readOutlineThickness) var readOutlineThickness

let post: any Post1Providing
let favoredLink: PostViewNavigationLink?
let overridePostSize: PostSize?

var postSize: PostSize {
overridePostSize ?? settingsPostSize
}

@ViewBuilder let embeddedContent: () -> EmbeddedContent

init(
Expand All @@ -50,7 +57,14 @@ struct FeedPostView<EmbeddedContent: View>: View {
}
} else {
content
.contentShape(.contextMenuPreview, .rect(cornerRadius: Constants.main.standardSpacing))
.overlay(alignment: .topLeading) {
if differentiateWithoutColor, !(post.read_ ?? false), readPostIndicator == .outline {
RoundedRectangle(cornerRadius: postSize.swipeBehavior.cornerRadius)
.stroke(lineWidth: .init(readOutlineThickness))
.foregroundStyle(palette.secondary)
}
}
.contentShape(.contextMenuPreview, .rect(cornerRadius: postSize.swipeBehavior.cornerRadius))
.quickSwipes(post.swipeActions(behavior: postSize.swipeBehavior))
.contextMenu { post.allMenuActions(
showAllActions: false,
Expand Down Expand Up @@ -79,7 +93,7 @@ struct FeedPostView<EmbeddedContent: View>: View {

@ViewBuilder
var content: some View {
switch overridePostSize ?? postSize {
switch postSize {
case .compact:
CompactPostView(post: post)
case .tile:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,12 @@ struct HeadlinePostView<EmbeddedContent: View>: View {
@Setting(\.showPostCreator) var alwaysShowCreator
@Setting(\.showPersonAvatar) var showPersonAvatar
@Setting(\.showCommunityAvatar) var showCommunityAvatar
@Setting(\.readPostIndicator) var readPostIndicator

@Environment(CommentTreeTracker.self) private var commentTreeTracker: CommentTreeTracker?
@Environment(Palette.self) var palette: Palette
@Environment(\.communityContext) var communityContext: (any Community1Providing)?
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

let post: any Post1Providing
let embeddedContent: EmbeddedContent
Expand Down Expand Up @@ -54,6 +56,10 @@ struct HeadlinePostView<EmbeddedContent: View>: View {

Spacer()

if differentiateWithoutColor, readPostIndicator == .checkmark, post.read_ ?? false {
ReadCheck()
}

if post.nsfw {
Image(Icons.nsfwTag)
.foregroundStyle(palette.warning)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,12 @@ struct LargePostView: View {
@Setting(\.showPersonAvatar) private var showPersonAvatar
@Setting(\.showCommunityAvatar) private var showCommunityAvatar
@Setting(\.blurNsfw) var blurNsfw
@Setting(\.readPostIndicator) var readPostIndicator

@Environment(Palette.self) private var palette: Palette
@Environment(CommentTreeTracker.self) private var commentTreeTracker: CommentTreeTracker?
@Environment(\.communityContext) private var communityContext
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

let post: any Post1Providing
let isPostPage: Bool
Expand Down Expand Up @@ -63,11 +65,15 @@ struct LargePostView: View {

Spacer()

if !isPostPage, differentiateWithoutColor, readPostIndicator == .checkmark, post.read_ ?? false {
ReadCheck()
}

if post.nsfw {
Image(Icons.nsfwTag)
.foregroundStyle(palette.warning)
}

if !isPostPage {
PostEllipsisMenus(post: post)
}
Expand Down
7 changes: 7 additions & 0 deletions Mlem/App/Views/Root/Tabs/Feeds/Feed Posts/TilePostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,14 @@ import NukeUI
import SwiftUI

struct TilePostView: View {
@Setting(\.readPostIndicator) var readPostIndicator

@Environment(CommentTreeTracker.self) private var commentTreeTracker: CommentTreeTracker?
@Environment(NavigationLayer.self) var navigation
@Environment(Palette.self) var palette: Palette
@Environment(\.communityContext) var communityContext: (any Community1Providing)?
@Environment(\.parentFrameWidth) var parentFrameWidth: CGFloat
@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

let post: any Post1Providing

Expand Down Expand Up @@ -88,6 +91,10 @@ struct TilePostView: View {

Spacer()

if differentiateWithoutColor, readPostIndicator == .checkmark, post.read_ ?? false {
ReadCheck(tiled: true)
}

score
}
.frame(maxWidth: .infinity)
Expand Down
59 changes: 59 additions & 0 deletions Mlem/App/Views/Root/Tabs/Settings/AccessibilitySettingsView.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// AccessibilitySettingsView.swift
// Mlem
//
// Created by Eric Andrews on 2024-12-25.
//

import SwiftUI

struct AccessibilitySettingsView: View {

@Environment(\.accessibilityDifferentiateWithoutColor) var differentiateWithoutColor

@Setting(\.readPostIndicator) var readPostIndicator
@Setting(\.readOutlineThickness) var readOutlineThickness

@State var readBarThicknessSlider: Double

init() {
@Setting(\.readOutlineThickness) var readOutlineThickness
self._readBarThicknessSlider = .init(wrappedValue: Double(readOutlineThickness))
}

var body: some View {
List {
Section("Differentiate Without Color") {
Picker("Read Post Indicator", selection: $readPostIndicator) {
ForEach(ReadPostIndicator.allCases, id: \.self) { item in
Text(item.label)
}
}

if readPostIndicator == .outline {
VStack(alignment: .leading) {
Text("Outline Thickness")

Slider(
value: $readBarThicknessSlider,
in: 1 ... 5,
step: 1
) {
Text("Outline Thickness")
} minimumValueLabel: {
Text(verbatim: "1")
} maximumValueLabel: {
Text(verbatim: "5")
} onEditingChanged: { editing in
if !editing {
readOutlineThickness = Int(readBarThicknessSlider)
}
}
}
}
} footer: {
Text("These settings control how Mlem behaves when the system-wide \"Differentiate Without Color\" option is enabled.")
}
}
}
}
2 changes: 2 additions & 0 deletions Mlem/App/Views/Root/Tabs/Settings/SettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ struct SettingsView: View {
Section {
NavigationLink("General", systemImage: "gear", destination: .settings(.general))
.tint(palette.neutralAccent)
NavigationLink("Accessibility", systemImage: "hand.point.up.braille.fill", destination: .settings(.accessibility))
.tint(palette.colorfulAccent(2))
NavigationLink("Links", systemImage: Icons.websiteAddress, destination: .settings(.links))
.tint(palette.colorfulAccent(6))
NavigationLink("Sorting", systemImage: "arrow.up.and.down.text.horizontal", destination: .settings(.sorting))
Expand Down
Loading

0 comments on commit e50d2cf

Please sign in to comment.