IOS-80 Add AXCustomContent to ProfileCardView (#979)
This commit is contained in:
parent
85ad331a5e
commit
f0753e9d0d
|
@ -508,7 +508,8 @@
|
||||||
"my_followers": "followers",
|
"my_followers": "followers",
|
||||||
"other_posts": "posts",
|
"other_posts": "posts",
|
||||||
"other_following": "following",
|
"other_following": "following",
|
||||||
"other_followers": "followers"
|
"other_followers": "followers",
|
||||||
|
"familiar_followers": "mutuals"
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"joined": "Joined",
|
"joined": "Joined",
|
||||||
|
|
|
@ -553,7 +553,8 @@
|
||||||
"my_followers": "followers",
|
"my_followers": "followers",
|
||||||
"other_posts": "posts",
|
"other_posts": "posts",
|
||||||
"other_following": "following",
|
"other_following": "following",
|
||||||
"other_followers": "followers"
|
"other_followers": "followers",
|
||||||
|
"familiar_followers": "mutuals"
|
||||||
},
|
},
|
||||||
"fields": {
|
"fields": {
|
||||||
"joined": "Joined",
|
"joined": "Joined",
|
||||||
|
|
|
@ -70,7 +70,13 @@ extension DiscoveryForYouViewController {
|
||||||
.receive(on: DispatchQueue.main)
|
.receive(on: DispatchQueue.main)
|
||||||
.sink { [weak self] isFetching in
|
.sink { [weak self] isFetching in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
if !isFetching {
|
if isFetching {
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 0.1) {
|
||||||
|
if !self.refreshControl.isRefreshing {
|
||||||
|
self.refreshControl.beginRefreshing()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
self.refreshControl.endRefreshing()
|
self.refreshControl.endRefreshing()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -899,6 +899,8 @@ public enum L10n {
|
||||||
public static let showBannerImage = L10n.tr("Localizable", "Scene.Profile.Accessibility.ShowBannerImage", fallback: "Show banner image")
|
public static let showBannerImage = L10n.tr("Localizable", "Scene.Profile.Accessibility.ShowBannerImage", fallback: "Show banner image")
|
||||||
}
|
}
|
||||||
public enum Dashboard {
|
public enum Dashboard {
|
||||||
|
/// mutuals
|
||||||
|
public static let familiarFollowers = L10n.tr("Localizable", "Scene.Profile.Dashboard.FamiliarFollowers", fallback: "mutuals")
|
||||||
/// followers
|
/// followers
|
||||||
public static let myFollowers = L10n.tr("Localizable", "Scene.Profile.Dashboard.MyFollowers", fallback: "followers")
|
public static let myFollowers = L10n.tr("Localizable", "Scene.Profile.Dashboard.MyFollowers", fallback: "followers")
|
||||||
/// following
|
/// following
|
||||||
|
|
|
@ -311,6 +311,7 @@ uploaded to Mastodon.";
|
||||||
"Scene.Profile.Accessibility.EditAvatarImage" = "Edit avatar image";
|
"Scene.Profile.Accessibility.EditAvatarImage" = "Edit avatar image";
|
||||||
"Scene.Profile.Accessibility.ShowAvatarImage" = "Show avatar image";
|
"Scene.Profile.Accessibility.ShowAvatarImage" = "Show avatar image";
|
||||||
"Scene.Profile.Accessibility.ShowBannerImage" = "Show banner image";
|
"Scene.Profile.Accessibility.ShowBannerImage" = "Show banner image";
|
||||||
|
"Scene.Profile.Dashboard.FamiliarFollowers" = "mutuals";
|
||||||
"Scene.Profile.Dashboard.MyFollowers" = "followers";
|
"Scene.Profile.Dashboard.MyFollowers" = "followers";
|
||||||
"Scene.Profile.Dashboard.MyFollowing" = "following";
|
"Scene.Profile.Dashboard.MyFollowing" = "following";
|
||||||
"Scene.Profile.Dashboard.MyPosts" = "posts";
|
"Scene.Profile.Dashboard.MyPosts" = "posts";
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
// Copyright © 2023 Mastodon gGmbH. All rights reserved.
|
||||||
|
|
||||||
|
import Accessibility
|
||||||
|
|
||||||
|
extension AXCustomContent {
|
||||||
|
convenience init?(label: String, value: String?) {
|
||||||
|
if let value, !value.isEmpty {
|
||||||
|
self.init(label: label, value: value)
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
convenience init?(label: String, value: (some BinaryInteger)?) {
|
||||||
|
if let value {
|
||||||
|
self.init(label: label, value: value.formatted())
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -7,6 +7,7 @@
|
||||||
|
|
||||||
import Meta
|
import Meta
|
||||||
import MastodonLocalization
|
import MastodonLocalization
|
||||||
|
import Foundation
|
||||||
|
|
||||||
extension Meta {
|
extension Meta {
|
||||||
public var accessibilityLabel: String? {
|
public var accessibilityLabel: String? {
|
||||||
|
@ -25,3 +26,14 @@ extension Meta {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
extension MetaContent {
|
||||||
|
public var accessibilityLabel: String {
|
||||||
|
return entities.reversed().reduce(string) { string, entity in
|
||||||
|
if case .emoji(_, let shortcode, _, _) = entity.meta {
|
||||||
|
return (string as NSString).replacingCharacters(in: entity.range, with: ":" + shortcode + ":")
|
||||||
|
}
|
||||||
|
return string
|
||||||
|
} as String
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,6 +9,7 @@ import os.log
|
||||||
import UIKit
|
import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
import CoreDataStack
|
import CoreDataStack
|
||||||
|
import Meta
|
||||||
import MastodonCore
|
import MastodonCore
|
||||||
import MastodonMeta
|
import MastodonMeta
|
||||||
import MastodonLocalization
|
import MastodonLocalization
|
||||||
|
@ -23,6 +24,8 @@ extension FamiliarFollowersDashboardView {
|
||||||
@Published var names: [String] = []
|
@Published var names: [String] = []
|
||||||
@Published var emojis: MastodonContent.Emojis = [:]
|
@Published var emojis: MastodonContent.Emojis = [:]
|
||||||
@Published var backgroundColor: UIColor?
|
@Published var backgroundColor: UIColor?
|
||||||
|
|
||||||
|
@Published var label: MetaContent?
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +77,11 @@ extension FamiliarFollowersDashboardView.ViewModel {
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
Publishers.CombineLatest(
|
let label = Publishers.CombineLatest(
|
||||||
$names,
|
$names,
|
||||||
$emojis
|
$emojis
|
||||||
)
|
)
|
||||||
.sink { names, emojis in
|
.map { (names, emojis) -> MetaContent in
|
||||||
let content: String = {
|
let content: String = {
|
||||||
guard names.count > 0 else { return " " }
|
guard names.count > 0 else { return " " }
|
||||||
|
|
||||||
|
@ -97,13 +100,18 @@ extension FamiliarFollowersDashboardView.ViewModel {
|
||||||
}()
|
}()
|
||||||
let document = MastodonContent(content: content, emojis: emojis)
|
let document = MastodonContent(content: content, emojis: emojis)
|
||||||
do {
|
do {
|
||||||
let metaContent = try MastodonMetaContent.convert(document: document)
|
return try MastodonMetaContent.convert(document: document)
|
||||||
view.descriptionMetaLabel.configure(content: metaContent)
|
|
||||||
} catch {
|
} catch {
|
||||||
assertionFailure()
|
assertionFailure()
|
||||||
view.descriptionMetaLabel.configure(content: PlaintextMetaContent(string: content))
|
return PlaintextMetaContent(string: content)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
label
|
||||||
|
.sink { [weak self] metaContent in
|
||||||
|
view.descriptionMetaLabel.configure(content: metaContent)
|
||||||
|
self?.label = metaContent
|
||||||
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,5 +246,47 @@ extension ProfileCardView.ViewModel {
|
||||||
view.accessibilityLabel = accessibilityLabel
|
view.accessibilityLabel = accessibilityLabel
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
|
let statusesContent = $statusesCount
|
||||||
|
.removeDuplicates()
|
||||||
|
.map {
|
||||||
|
AXCustomContent(
|
||||||
|
label: L10n.Scene.Profile.Dashboard.otherPosts,
|
||||||
|
value: $0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let followingContent = $followingCount
|
||||||
|
.removeDuplicates()
|
||||||
|
.map {
|
||||||
|
AXCustomContent(
|
||||||
|
label: L10n.Scene.Profile.Dashboard.otherFollowing,
|
||||||
|
value: $0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let followersContent = $followersCount
|
||||||
|
.removeDuplicates()
|
||||||
|
.map {
|
||||||
|
AXCustomContent(
|
||||||
|
label: L10n.Scene.Profile.Dashboard.otherFollowers,
|
||||||
|
value: $0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
let familiarContent = view.familiarFollowersDashboardView.viewModel.$label
|
||||||
|
.map { $0?.accessibilityLabel }
|
||||||
|
.removeDuplicates()
|
||||||
|
.map {
|
||||||
|
AXCustomContent(
|
||||||
|
label: L10n.Scene.Profile.Dashboard.familiarFollowers,
|
||||||
|
value: $0
|
||||||
|
)
|
||||||
|
}
|
||||||
|
Publishers.CombineLatest4(
|
||||||
|
statusesContent,
|
||||||
|
followingContent,
|
||||||
|
followersContent,
|
||||||
|
familiarContent
|
||||||
|
).sink { statuses, following, followers, familiar in
|
||||||
|
view.accessibilityCustomContent = [statuses, following, followers, familiar].compactMap { $0 }
|
||||||
|
}.store(in: &disposeBag)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,7 +16,7 @@ public protocol ProfileCardViewDelegate: AnyObject {
|
||||||
func profileCardView(_ profileCardView: ProfileCardView, familiarFollowersDashboardViewDidPressed view: FamiliarFollowersDashboardView)
|
func profileCardView(_ profileCardView: ProfileCardView, familiarFollowersDashboardViewDidPressed view: FamiliarFollowersDashboardView)
|
||||||
}
|
}
|
||||||
|
|
||||||
public final class ProfileCardView: UIView {
|
public final class ProfileCardView: UIView, AXCustomContentProvider {
|
||||||
|
|
||||||
let logger = Logger(subsystem: "ProfileCardView", category: "View")
|
let logger = Logger(subsystem: "ProfileCardView", category: "View")
|
||||||
|
|
||||||
|
@ -28,6 +28,8 @@ public final class ProfileCardView: UIView {
|
||||||
private var _disposeBag = Set<AnyCancellable>()
|
private var _disposeBag = Set<AnyCancellable>()
|
||||||
var disposeBag = Set<AnyCancellable>()
|
var disposeBag = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
public var accessibilityCustomContent: [AXCustomContent]! = []
|
||||||
|
|
||||||
let container = UIStackView()
|
let container = UIStackView()
|
||||||
|
|
||||||
let bannerImageView: UIImageView = {
|
let bannerImageView: UIImageView = {
|
||||||
|
|
Loading…
Reference in New Issue