IOS-80 Add AXCustomContent to ProfileCardView (#979)
This commit is contained in:
parent
85ad331a5e
commit
f0753e9d0d
|
@ -508,7 +508,8 @@
|
|||
"my_followers": "followers",
|
||||
"other_posts": "posts",
|
||||
"other_following": "following",
|
||||
"other_followers": "followers"
|
||||
"other_followers": "followers",
|
||||
"familiar_followers": "mutuals"
|
||||
},
|
||||
"fields": {
|
||||
"joined": "Joined",
|
||||
|
|
|
@ -553,7 +553,8 @@
|
|||
"my_followers": "followers",
|
||||
"other_posts": "posts",
|
||||
"other_following": "following",
|
||||
"other_followers": "followers"
|
||||
"other_followers": "followers",
|
||||
"familiar_followers": "mutuals"
|
||||
},
|
||||
"fields": {
|
||||
"joined": "Joined",
|
||||
|
|
|
@ -70,7 +70,13 @@ extension DiscoveryForYouViewController {
|
|||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] isFetching in
|
||||
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()
|
||||
}
|
||||
}
|
||||
|
|
|
@ -899,6 +899,8 @@ public enum L10n {
|
|||
public static let showBannerImage = L10n.tr("Localizable", "Scene.Profile.Accessibility.ShowBannerImage", fallback: "Show banner image")
|
||||
}
|
||||
public enum Dashboard {
|
||||
/// mutuals
|
||||
public static let familiarFollowers = L10n.tr("Localizable", "Scene.Profile.Dashboard.FamiliarFollowers", fallback: "mutuals")
|
||||
/// followers
|
||||
public static let myFollowers = L10n.tr("Localizable", "Scene.Profile.Dashboard.MyFollowers", fallback: "followers")
|
||||
/// following
|
||||
|
|
|
@ -311,6 +311,7 @@ uploaded to Mastodon.";
|
|||
"Scene.Profile.Accessibility.EditAvatarImage" = "Edit avatar image";
|
||||
"Scene.Profile.Accessibility.ShowAvatarImage" = "Show avatar image";
|
||||
"Scene.Profile.Accessibility.ShowBannerImage" = "Show banner image";
|
||||
"Scene.Profile.Dashboard.FamiliarFollowers" = "mutuals";
|
||||
"Scene.Profile.Dashboard.MyFollowers" = "followers";
|
||||
"Scene.Profile.Dashboard.MyFollowing" = "following";
|
||||
"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 MastodonLocalization
|
||||
import Foundation
|
||||
|
||||
extension Meta {
|
||||
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 Combine
|
||||
import CoreDataStack
|
||||
import Meta
|
||||
import MastodonCore
|
||||
import MastodonMeta
|
||||
import MastodonLocalization
|
||||
|
@ -23,6 +24,8 @@ extension FamiliarFollowersDashboardView {
|
|||
@Published var names: [String] = []
|
||||
@Published var emojis: MastodonContent.Emojis = [:]
|
||||
@Published var backgroundColor: UIColor?
|
||||
|
||||
@Published var label: MetaContent?
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -74,11 +77,11 @@ extension FamiliarFollowersDashboardView.ViewModel {
|
|||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
Publishers.CombineLatest(
|
||||
let label = Publishers.CombineLatest(
|
||||
$names,
|
||||
$emojis
|
||||
)
|
||||
.sink { names, emojis in
|
||||
.map { (names, emojis) -> MetaContent in
|
||||
let content: String = {
|
||||
guard names.count > 0 else { return " " }
|
||||
|
||||
|
@ -97,13 +100,18 @@ extension FamiliarFollowersDashboardView.ViewModel {
|
|||
}()
|
||||
let document = MastodonContent(content: content, emojis: emojis)
|
||||
do {
|
||||
let metaContent = try MastodonMetaContent.convert(document: document)
|
||||
view.descriptionMetaLabel.configure(content: metaContent)
|
||||
return try MastodonMetaContent.convert(document: document)
|
||||
} catch {
|
||||
assertionFailure()
|
||||
view.descriptionMetaLabel.configure(content: PlaintextMetaContent(string: content))
|
||||
return PlaintextMetaContent(string: content)
|
||||
}
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
label
|
||||
.sink { [weak self] metaContent in
|
||||
view.descriptionMetaLabel.configure(content: metaContent)
|
||||
self?.label = metaContent
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -246,5 +246,47 @@ extension ProfileCardView.ViewModel {
|
|||
view.accessibilityLabel = accessibilityLabel
|
||||
}
|
||||
.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)
|
||||
}
|
||||
|
||||
public final class ProfileCardView: UIView {
|
||||
public final class ProfileCardView: UIView, AXCustomContentProvider {
|
||||
|
||||
let logger = Logger(subsystem: "ProfileCardView", category: "View")
|
||||
|
||||
|
@ -28,6 +28,8 @@ public final class ProfileCardView: UIView {
|
|||
private var _disposeBag = Set<AnyCancellable>()
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
public var accessibilityCustomContent: [AXCustomContent]! = []
|
||||
|
||||
let container = UIStackView()
|
||||
|
||||
let bannerImageView: UIImageView = {
|
||||
|
|
Loading…
Reference in New Issue