Merge pull request #613 from j-f1/joined-at

Add a “Joined” cell to the top of the About tab to match the web version
This commit is contained in:
Nathan Mattes 2022-12-18 14:30:57 +01:00 committed by GitHub
commit 3b77ed7612
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 67 additions and 92 deletions

View File

@ -453,6 +453,7 @@
"followers": "followers"
},
"fields": {
"joined": "Joined",
"add_row": "Add Row",
"placeholder": {
"label": "Label",

View File

@ -467,6 +467,7 @@
"followers": "followers"
},
"fields": {
"joined": "Joined",
"add_row": "Add Row",
"placeholder": {
"label": "Label",

View File

@ -11,10 +11,10 @@ import MastodonSDK
import MastodonMeta
enum ProfileFieldItem: Hashable {
case createdAt(date: Date)
case field(field: FieldValue)
case editField(field: FieldValue)
case addEntry
case noResult
}
extension ProfileFieldItem {

View File

@ -33,44 +33,60 @@ extension ProfileFieldSection {
collectionView.register(ProfileFieldCollectionViewHeaderFooterView.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: ProfileFieldCollectionViewHeaderFooterView.footerReuseIdentifer)
let fieldCellRegistration = UICollectionView.CellRegistration<ProfileFieldCollectionViewCell, ProfileFieldItem> { cell, indexPath, item in
guard case let .field(field) = item else { return }
let key, value: String
let emojiMeta: MastodonContent.Emojis
let verified: Bool
switch item {
case .field(field: let field):
key = field.name.value
value = field.value.value
emojiMeta = field.emojiMeta
verified = field.verifiedAt.value != nil
case .createdAt(date: let date):
key = L10n.Scene.Profile.Fields.joined
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
value = formatter.string(from: date)
emojiMeta = [:]
verified = false
default: return
}
// set key
let keyColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color : Asset.Colors.Label.secondary.color
do {
let mastodonContent = MastodonContent(content: field.name.value, emojis: field.emojiMeta)
let mastodonContent = MastodonContent(content: key, emojis: emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.keyMetaLabel.textAttributes[.foregroundColor] = keyColor
cell.keyMetaLabel.configure(content: metaContent)
} catch {
let content = PlaintextMetaContent(string: field.name.value)
let content = PlaintextMetaContent(string: key)
// cell.keyMetaLabel.textAttributes[.foregroundColor] = keyColor
cell.keyMetaLabel.configure(content: content)
}
// set value
let linkColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color : Asset.Colors.brand.color
do {
let mastodonContent = MastodonContent(content: field.value.value, emojis: field.emojiMeta)
let mastodonContent = MastodonContent(content: value, emojis: emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
cell.valueMetaLabel.linkAttributes[.foregroundColor] = Asset.Colors.brand.color
if field.verifiedAt.value != nil {
cell.valueMetaLabel.linkAttributes[.foregroundColor] = Asset.Scene.Profile.About.bioAboutFieldVerifiedLink.color
}
cell.valueMetaLabel.linkAttributes[.foregroundColor] = linkColor
cell.valueMetaLabel.configure(content: metaContent)
} catch {
let content = PlaintextMetaContent(string: field.value.value)
let content = PlaintextMetaContent(string: value)
cell.valueMetaLabel.linkAttributes[.foregroundColor] = linkColor
cell.valueMetaLabel.configure(content: content)
}
// set background
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColor = UIColor.secondarySystemBackground
if (field.verifiedAt.value != nil) {
backgroundConfiguration.backgroundColor = Asset.Scene.Profile.About.bioAboutFieldVerifiedBackground.color
}
backgroundConfiguration.backgroundColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedBackground.color : UIColor.secondarySystemBackground
cell.backgroundConfiguration = backgroundConfiguration
// set checkmark and edit menu label
cell.checkmark.isHidden = true
cell.checkmarkPopoverString = nil
if let verifiedAt = field.verifiedAt.value {
if case .field(let field) = item, let verifiedAt = field.verifiedAt.value {
cell.checkmark.isHidden = false
let formatter = DateFormatter()
formatter.dateStyle = .medium
@ -78,6 +94,9 @@ extension ProfileFieldSection {
let dateString = formatter.string(from: verifiedAt)
cell.checkmark.accessibilityLabel = L10n.Scene.Profile.Fields.Verified.long(dateString)
cell.checkmarkPopoverString = L10n.Scene.Profile.Fields.Verified.short(dateString)
} else {
cell.checkmark.isHidden = true
cell.checkmarkPopoverString = nil
}
cell.delegate = configuration.profileFieldCollectionViewCellDelegate
@ -128,26 +147,10 @@ extension ProfileFieldSection {
}
cell.backgroundConfiguration = backgroundConfiguration
}
let noResultCellRegistration = UICollectionView.CellRegistration<UICollectionViewListCell, ProfileFieldItem> { cell, indexPath, item in
guard case .noResult = item else { return }
var contentConfiguration = cell.defaultContentConfiguration()
contentConfiguration.text = L10n.Scene.Search.Searching.EmptyState.noResults // FIXME:
contentConfiguration.textProperties.alignment = .center
cell.contentConfiguration = contentConfiguration
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColorTransformer = .init { _ in
return .secondarySystemBackground
}
cell.backgroundConfiguration = backgroundConfiguration
}
let dataSource = UICollectionViewDiffableDataSource<ProfileFieldSection, ProfileFieldItem>(collectionView: collectionView) { collectionView, indexPath, item in
switch item {
case .field:
case .field, .createdAt:
return collectionView.dequeueConfiguredReusableCell(
using: fieldCellRegistration,
for: indexPath,
@ -165,12 +168,6 @@ extension ProfileFieldSection {
for: indexPath,
item: item
)
case .noResult:
return collectionView.dequeueConfiguredReusableCell(
using: noResultCellRegistration,
for: indexPath,
item: item
)
}
}

View File

@ -58,7 +58,7 @@ extension ProfileFieldCollectionViewCell {
private func _init() {
// Setup colors
checkmark.tintColor = Asset.Scene.Profile.About.bioAboutFieldVerifiedCheckmark.color;
checkmark.tintColor = Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color;
// Setup gestures
tapGesture.addTarget(self, action: #selector(ProfileFieldCollectionViewCell.didTapCheckmark(_:)))

View File

@ -50,23 +50,33 @@ extension ProfileAboutViewModel {
var snapshot = NSDiffableDataSourceSnapshot<ProfileFieldSection, ProfileFieldItem>()
snapshot.appendSections([.main])
diffableDataSource.apply(snapshot)
Publishers.CombineLatest4(
let fields = Publishers.CombineLatest3(
$isEditing.removeDuplicates(),
profileInfo.$fields.removeDuplicates(),
profileInfoEditing.$fields.removeDuplicates(),
profileInfoEditing.$fields.removeDuplicates()
).map { isEditing, displayFields, editingFields in
isEditing ? editingFields : displayFields
}
Publishers.CombineLatest4(
$isEditing.removeDuplicates(),
$createdAt.removeDuplicates(),
fields,
$emojiMeta.removeDuplicates()
)
.throttle(for: 0.3, scheduler: DispatchQueue.main, latest: true)
.sink { [weak self] isEditing, displayFields, editingFields, emojiMeta in
.sink { [weak self] isEditing, createdAt, fields, emojiMeta in
guard let self = self else { return }
guard let diffableDataSource = self.diffableDataSource else { return }
var snapshot = NSDiffableDataSourceSnapshot<ProfileFieldSection, ProfileFieldItem>()
snapshot.appendSections([.main])
let fields: [ProfileFieldItem.FieldValue] = isEditing ? editingFields : displayFields
var items: [ProfileFieldItem] = fields.map { field in
var items: [ProfileFieldItem] = [
.createdAt(date: createdAt),
] + fields.map { field in
if isEditing {
return ProfileFieldItem.editField(field: field)
} else {
@ -78,10 +88,6 @@ extension ProfileAboutViewModel {
items.append(.addEntry)
}
if !isEditing, items.isEmpty {
items.append(.noResult)
}
snapshot.appendItems(items, toSection: .main)
diffableDataSource.apply(snapshot, animatingDifferences: false, completion: nil)

View File

@ -31,6 +31,7 @@ final class ProfileAboutViewModel {
@Published var fields: [MastodonField] = []
@Published var emojiMeta: MastodonContent.Emojis = [:]
@Published var createdAt: Date = Date()
init(context: AppContext) {
self.context = context
@ -46,6 +47,11 @@ final class ProfileAboutViewModel {
.compactMap { $0 }
.flatMap { $0.publisher(for: \.fields) }
.assign(to: &$fields)
$user
.compactMap { $0 }
.flatMap { $0.publisher(for: \.createdAt) }
.assign(to: &$createdAt)
Publishers.CombineLatest(
$fields,

View File

@ -1,38 +0,0 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.371",
"green" : "0.565",
"red" : "0.290"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.603",
"green" : "0.742",
"red" : "0.476"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -175,8 +175,7 @@ public enum Asset {
public enum Profile {
public enum About {
public static let bioAboutFieldVerifiedBackground = ColorAsset(name: "Scene/Profile/About/bio.about.field.verified.background")
public static let bioAboutFieldVerifiedCheckmark = ColorAsset(name: "Scene/Profile/About/bio.about.field.verified.checkmark")
public static let bioAboutFieldVerifiedLink = ColorAsset(name: "Scene/Profile/About/bio.about.field.verified.link")
public static let bioAboutFieldVerifiedText = ColorAsset(name: "Scene/Profile/About/bio.about.field.verified.text")
}
public enum Banner {
public static let bioEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/bio.edit.background.gray")

View File

@ -799,6 +799,8 @@ public enum L10n {
public enum Fields {
/// Add Row
public static let addRow = L10n.tr("Localizable", "Scene.Profile.Fields.AddRow", fallback: "Add Row")
/// Joined
public static let joined = L10n.tr("Localizable", "Scene.Profile.Fields.Joined", fallback: "Joined")
public enum Placeholder {
/// Content
public static let content = L10n.tr("Localizable", "Scene.Profile.Fields.Placeholder.Content", fallback: "Content")

View File

@ -286,6 +286,7 @@ uploaded to Mastodon.";
"Scene.Profile.Dashboard.Following" = "following";
"Scene.Profile.Dashboard.Posts" = "posts";
"Scene.Profile.Fields.AddRow" = "Add Row";
"Scene.Profile.Fields.Joined" = "Joined";
"Scene.Profile.Fields.Placeholder.Content" = "Content";
"Scene.Profile.Fields.Placeholder.Label" = "Label";
"Scene.Profile.Fields.Verified.Long" = "Ownership of this link was checked on %@";