Merge pull request #1143 from mastodon/ios-130-badge-verified-links

Update design for verified links in profile (IOS-130)
This commit is contained in:
Nathan Mattes 2023-11-09 11:38:19 +01:00 committed by GitHub
commit 12ed4a70cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 104 additions and 255 deletions

View File

@ -35,28 +35,26 @@ extension ProfileFieldSection {
let fieldCellRegistration = UICollectionView.CellRegistration<ProfileFieldCollectionViewCell, ProfileFieldItem> { cell, indexPath, item in
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
formatter.timeZone = TimeZone(identifier: "UTC")
value = formatter.string(from: date)
emojiMeta = [:]
verified = false
default: return
case .field(field: let field):
key = field.name.value
value = field.value.value
emojiMeta = field.emojiMeta
case .createdAt(date: let date):
key = L10n.Scene.Profile.Fields.joined
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .none
formatter.timeZone = TimeZone(identifier: "UTC")
value = formatter.string(from: date)
emojiMeta = [:]
case .addEntry, .editField(_): return
}
// set key
let keyColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color : Asset.Colors.Label.secondary.color
let keyColor = Asset.Colors.Label.secondary.color
do {
let mastodonContent = MastodonContent(content: key, emojis: emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
@ -69,7 +67,7 @@ extension ProfileFieldSection {
}
// set value
let linkColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color : Asset.Colors.Brand.blurple.color
let linkColor = Asset.Colors.Brand.blurple.color
do {
let mastodonContent = MastodonContent(content: value, emojis: emojiMeta)
let metaContent = try MastodonMetaContent.convert(document: mastodonContent)
@ -83,7 +81,7 @@ extension ProfileFieldSection {
// set background
var backgroundConfiguration = UIBackgroundConfiguration.listPlainCell()
backgroundConfiguration.backgroundColor = verified ? Asset.Scene.Profile.About.bioAboutFieldVerifiedBackground.color : UIColor.secondarySystemBackground
backgroundConfiguration.backgroundColor = UIColor.secondarySystemBackground
cell.backgroundConfiguration = backgroundConfiguration
// set checkmark and edit menu label

View File

@ -25,7 +25,7 @@ final class ProfileFieldCollectionViewCell: UICollectionViewCell {
let keyMetaLabel = MetaLabel(style: .profileFieldName)
let valueMetaLabel = MetaLabel(style: .profileFieldValue)
let checkmark = UIImageView(image: Asset.Editing.checkmark.image.withRenderingMode(.alwaysTemplate))
let checkmark: UIImageView
var checkmarkPopoverString: String? = nil;
let tapGesture = UITapGestureRecognizer();
var editMenuInteraction: UIEditMenuInteraction!
@ -37,26 +37,16 @@ final class ProfileFieldCollectionViewCell: UICollectionViewCell {
}
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension ProfileFieldCollectionViewCell {
private func _init() {
// Setup colors
checkmark = UIImageView(image: Asset.Scene.Profile.About.verifiedCheckmark.image.withRenderingMode(.alwaysTemplate))
checkmark.tintColor = Asset.Colors.Brand.blurple.color
checkmark.translatesAutoresizingMaskIntoConstraints = false
super.init(frame: frame)
editMenuInteraction = UIEditMenuInteraction(delegate: self)
// Setup colors
checkmark.tintColor = Asset.Scene.Profile.About.bioAboutFieldVerifiedText.color;
// Setup gestures
tapGesture.addTarget(self, action: #selector(ProfileFieldCollectionViewCell.didTapCheckmark(_:)))
checkmark.addGestureRecognizer(tapGesture)
@ -76,36 +66,45 @@ extension ProfileFieldCollectionViewCell {
containerStackView.preservesSuperviewLayoutMargins = true
containerStackView.isLayoutMarginsRelativeArrangement = true
containerStackView.translatesAutoresizingMaskIntoConstraints = false
addSubview(containerStackView)
contentView.addSubview(containerStackView)
NSLayoutConstraint.activate([
containerStackView.topAnchor.constraint(equalTo: topAnchor, constant: 11),
containerStackView.leadingAnchor.constraint(equalTo: leadingAnchor),
containerStackView.trailingAnchor.constraint(equalTo: trailingAnchor),
bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 11),
containerStackView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 8),
containerStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor),
contentView.trailingAnchor.constraint(equalTo: containerStackView.trailingAnchor),
contentView.bottomAnchor.constraint(equalTo: containerStackView.bottomAnchor, constant: 8),
checkmark.heightAnchor.constraint(equalToConstant: 22),
checkmark.widthAnchor.constraint(equalTo: checkmark.heightAnchor),
])
// metaContainer: V - [ keyMetaLabel | valueContainer ]
// metaContainer: h - [ keyValueContainer | checkmark ]
let metaContainer = UIStackView()
metaContainer.axis = .vertical
metaContainer.axis = .horizontal
metaContainer.spacing = 2
metaContainer.alignment = .center
// valueContainer: v - [ keyMetaLabel | valueMetaLabel ]
let keyValueContainer = UIStackView()
keyValueContainer.axis = .vertical
keyValueContainer.alignment = .leading
keyValueContainer.spacing = 2
containerStackView.addArrangedSubview(metaContainer)
// valueContainer: H - [ valueMetaLabel | checkmark ]
let valueContainer = UIStackView()
valueContainer.axis = .horizontal
valueContainer.spacing = 2
metaContainer.addArrangedSubview(keyMetaLabel)
valueContainer.addArrangedSubview(valueMetaLabel)
valueContainer.addArrangedSubview(checkmark)
metaContainer.addArrangedSubview(valueContainer)
keyValueContainer.addArrangedSubview(keyMetaLabel)
keyValueContainer.addArrangedSubview(valueMetaLabel)
metaContainer.addArrangedSubview(keyValueContainer)
metaContainer.addArrangedSubview(checkmark)
keyMetaLabel.linkDelegate = self
valueMetaLabel.linkDelegate = self
isAccessibilityElement = true
}
required init?(coder: NSCoder) { fatalError("Just ... don't.") }
//MARK: - Actions
@objc public func didTapCheckmark(_ recognizer: UITapGestureRecognizer) {
editMenuInteraction?.presentEditMenu(with: UIEditMenuConfiguration(identifier: nil, sourcePoint: recognizer.location(in: checkmark)))
}
@ -120,6 +119,7 @@ extension ProfileFieldCollectionViewCell {
return result
}
//MARK: - Accessibility
override func accessibilityActivate() -> Bool {
if let (_, meta) = valueMetas.first {
delegate?.profileFieldCollectionViewCell(self, metaLabel: valueMetaLabel, didSelectMeta: meta)
@ -143,23 +143,10 @@ extension ProfileFieldCollectionViewCell {
}
set {}
}
}
// UIMenuController boilerplate
@available(iOS, deprecated: 16, message: "Can be removed when target version is >=16 -- boilerplate to maintain compatibility with UIMenuController")
extension ProfileFieldCollectionViewCell {
override var canBecomeFirstResponder: Bool { true }
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == #selector(dismissVerifiedMenu) {
return true
}
return super.canPerformAction(action, withSender: sender)
}
@objc public func dismissVerifiedMenu() {
UIMenuController.shared.hideMenu()
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
super.traitCollectionDidChange(previousTraitCollection)
checkmark.image = Asset.Scene.Profile.About.verifiedCheckmark.image.withRenderingMode(.alwaysTemplate)
}
}

View File

@ -14,18 +14,7 @@ final class ProfileFieldCollectionViewHeaderFooterView: UICollectionReusableView
override init(frame: CGRect) {
super.init(frame: frame)
_init()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
_init()
}
}
extension ProfileFieldCollectionViewHeaderFooterView {
private func _init() {
}
required init?(coder: NSCoder) { fatalError("Not implemented") }
}

View File

@ -1,15 +0,0 @@
{
"images" : [
{
"filename" : "checkmark.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true
}
}

View File

@ -1,76 +0,0 @@
%PDF-1.7
1 0 obj
<< >>
endobj
2 0 obj
<< /Length 3 0 R >>
stream
/DeviceRGB CS
/DeviceRGB cs
q
1.000000 0.000000 -0.000000 1.000000 3.250000 5.105469 cm
0.129412 0.129412 0.129412 scn
1.280330 5.924861 m
0.987437 6.217754 0.512563 6.217754 0.219670 5.924861 c
-0.073223 5.631968 -0.073223 5.157095 0.219670 4.864202 c
4.719670 0.364201 l
5.012563 0.071307 5.487436 0.071307 5.780330 0.364201 c
16.780331 11.364201 l
17.073223 11.657094 17.073223 12.131968 16.780331 12.424861 c
16.487438 12.717754 16.012562 12.717754 15.719669 12.424861 c
5.250000 1.955191 l
1.280330 5.924861 l
h
f
n
Q
endstream
endobj
3 0 obj
523
endobj
4 0 obj
<< /Annots []
/Type /Page
/MediaBox [ 0.000000 0.000000 24.000000 24.000000 ]
/Resources 1 0 R
/Contents 2 0 R
/Parent 5 0 R
>>
endobj
5 0 obj
<< /Kids [ 4 0 R ]
/Count 1
/Type /Pages
>>
endobj
6 0 obj
<< /Pages 5 0 R
/Type /Catalog
>>
endobj
xref
0 7
0000000000 65535 f
0000000010 00000 n
0000000034 00000 n
0000000613 00000 n
0000000635 00000 n
0000000808 00000 n
0000000882 00000 n
trailer
<< /ID [ (some) (id) ]
/Root 6 0 R
/Size 7
>>
startxref
941
%%EOF

View File

@ -1,38 +0,0 @@
{
"colors" : [
{
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.852",
"green" : "0.894",
"red" : "0.835"
}
},
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"color" : {
"color-space" : "srgb",
"components" : {
"alpha" : "1.000",
"blue" : "0.354",
"green" : "0.353",
"red" : "0.268"
}
},
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

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

@ -0,0 +1,22 @@
{
"images" : [
{
"filename" : "checkmark.seal.svg",
"idiom" : "universal"
},
{
"appearances" : [
{
"appearance" : "luminosity",
"value" : "dark"
}
],
"filename" : "checkmark.seal.fill.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="44.3701" height="44.3897">
<g>
<rect height="44.3897" opacity="0" width="44.3701" x="0" y="0"/>
<path d="M10.3491 39.1187L14.5874 39.1187C14.978 39.1187 15.271 39.2358 15.564 39.5288L18.5718 42.5171C21.0327 44.9976 23.3179 44.978 25.7788 42.5171L28.7866 39.5288C29.0991 39.2358 29.3726 39.1187 29.7827 39.1187L34.0015 39.1187C37.4976 39.1187 39.1187 37.5171 39.1187 34.0015L39.1187 29.7827C39.1187 29.3726 39.2358 29.0991 39.5288 28.7866L42.5171 25.7788C44.9976 23.3179 44.978 21.0327 42.5171 18.5718L39.5288 15.564C39.2358 15.271 39.1187 14.978 39.1187 14.5874L39.1187 10.3491C39.1187 6.87257 37.5171 5.23194 34.0015 5.23194L29.7827 5.23194C29.3726 5.23194 29.0991 5.13428 28.7866 4.84132L25.7788 1.85303C23.3179-0.627434 21.0327-0.607903 18.5718 1.85303L15.564 4.84132C15.271 5.13428 14.978 5.23194 14.5874 5.23194L10.3491 5.23194C6.85303 5.23194 5.23194 6.8335 5.23194 10.3491L5.23194 14.5874C5.23194 14.978 5.13428 15.271 4.84132 15.564L1.85303 18.5718C-0.627434 21.0327-0.607903 23.3179 1.85303 25.7788L4.84132 28.7866C5.13428 29.0991 5.23194 29.3726 5.23194 29.7827L5.23194 34.0015C5.23194 37.4976 6.85303 39.1187 10.3491 39.1187ZM19.9976 31.7163C19.3335 31.7163 18.7866 31.4624 18.2788 30.7788L13.3765 24.7632C13.0835 24.3726 12.9077 23.9233 12.9077 23.4937C12.9077 22.5952 13.5913 21.8726 14.4898 21.8726C15.0366 21.8726 15.4663 22.0679 15.9546 22.7124L19.9194 27.8296L28.2593 14.4312C28.6304 13.8257 29.1382 13.5327 29.6655 13.5327C30.5054 13.5327 31.3062 14.1187 31.3062 15.0171C31.3062 15.4663 31.0523 15.9155 30.8179 16.3062L21.6382 30.7788C21.228 31.4038 20.6616 31.7163 19.9976 31.7163Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--Generator: Apple Native CoreSVG 175.5-->
<!DOCTYPE svg
PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="44.3506" height="44.5459">
<g>
<rect height="44.5459" opacity="0" width="44.3506" x="0" y="0"/>
<path d="M10.3491 39.1187L14.5679 39.1187C14.978 39.1187 15.271 39.2358 15.564 39.5288L18.5718 42.5171C21.0327 44.9976 23.3179 44.978 25.7788 42.5171L28.7866 39.5288C29.0796 39.2358 29.3726 39.1187 29.7827 39.1187L34.0015 39.1187C37.4976 39.1187 39.1187 37.5171 39.1187 34.0015L39.1187 29.7827C39.1187 29.3726 39.2358 29.0991 39.5288 28.7866L42.4976 25.7788C44.978 23.3179 44.9585 21.0523 42.4976 18.5718L39.5288 15.564C39.2358 15.271 39.1187 14.978 39.1187 14.5874L39.1187 10.3491C39.1187 6.87257 37.5171 5.23194 34.0015 5.23194L29.7827 5.23194C29.3726 5.23194 29.0796 5.13428 28.7866 4.84132L25.7788 1.85303C23.3179-0.627434 21.0327-0.607903 18.5718 1.85303L15.564 4.84132C15.271 5.13428 14.978 5.23194 14.5679 5.23194L10.3491 5.23194C6.85303 5.23194 5.23194 6.8335 5.23194 10.3491L5.23194 14.5874C5.23194 14.978 5.13428 15.271 4.84132 15.564L1.85303 18.5718C-0.627434 21.0523-0.607903 23.3179 1.85303 25.7788L4.84132 28.7866C5.13428 29.0991 5.23194 29.3726 5.23194 29.7827L5.23194 34.0015C5.23194 37.4976 6.85303 39.1187 10.3491 39.1187ZM10.3491 36.0132C8.61085 36.0132 8.33741 35.7398 8.33741 34.0015L8.33741 28.7476C8.33741 28.1616 8.16163 27.7124 7.73194 27.2827L4.04053 23.6108C2.81007 22.3608 2.81007 22.0093 4.04053 20.7593L7.73194 17.0874C8.16163 16.6577 8.33741 16.2085 8.33741 15.603L8.33741 10.3491C8.33741 8.59132 8.59132 8.33741 10.3491 8.33741L15.603 8.33741C16.2085 8.33741 16.6577 8.18116 17.0874 7.73194L20.7593 4.04053C22.0093 2.81007 22.3608 2.81007 23.5913 4.04053L27.2827 7.73194C27.6929 8.18116 28.1616 8.33741 28.7476 8.33741L34.0015 8.33741C35.7398 8.33741 36.0132 8.61085 36.0132 10.3491L36.0132 15.603C36.0132 16.2085 36.2085 16.6577 36.6382 17.0874L40.3296 20.7593C41.5601 22.0093 41.5601 22.3608 40.3296 23.6108L36.6382 27.2827C36.2085 27.7124 36.0132 28.1616 36.0132 28.7476L36.0132 34.0015C36.0132 35.7398 35.7398 36.0132 34.0015 36.0132L28.7476 36.0132C28.1616 36.0132 27.6929 36.189 27.2827 36.6382L23.5913 40.3296C22.3608 41.5601 22.0093 41.5601 20.7593 40.3296L17.0874 36.6382C16.6577 36.189 16.2085 36.0132 15.603 36.0132ZM20.0562 31.4429C20.7007 31.4429 21.2476 31.1304 21.6382 30.5444L30.564 16.4819C30.7788 16.1108 31.0327 15.6812 31.0327 15.2319C31.0327 14.3726 30.2515 13.8062 29.4507 13.8062C28.9429 13.8062 28.4546 14.0991 28.0835 14.6851L19.978 27.6929L16.1304 22.7124C15.6616 22.0874 15.2319 21.9116 14.7046 21.9116C13.8452 21.9116 13.1812 22.5952 13.1812 23.4741C13.1812 23.8843 13.3569 24.314 13.6304 24.6851L18.396 30.5444C18.8843 31.189 19.4116 31.4429 20.0562 31.4429Z" fill="#ffffff" fill-opacity="0.85"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.9 KiB

View File

@ -119,7 +119,6 @@ public enum Asset {
}
public enum Editing {
public static let checkmark20 = ImageAsset(name: "Editing/checkmark.20")
public static let checkmark = ImageAsset(name: "Editing/checkmark")
public static let xmark = ImageAsset(name: "Editing/xmark")
}
public enum Human {
@ -181,8 +180,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 bioAboutFieldVerifiedText = ColorAsset(name: "Scene/Profile/About/bio.about.field.verified.text")
public static let verifiedCheckmark = ImageAsset(name: "Scene/Profile/About/verified_checkmark")
}
public enum Banner {
public static let bioEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/bio.edit.background.gray")

View File

@ -78,11 +78,11 @@ extension MetaLabel {
textColor = Asset.Colors.Label.secondary.color
case .profileFieldName:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 13, weight: .semibold))
font = UIFontMetrics(forTextStyle: .caption1).scaledFont(for: .systemFont(ofSize: 12, weight: .regular))
textColor = Asset.Colors.Label.secondary.color
case .profileFieldValue:
font = UIFontMetrics(forTextStyle: .headline).scaledFont(for: .systemFont(ofSize: 17, weight: .regular))
font = UIFontMetrics(forTextStyle: .body).scaledFont(for: .systemFont(ofSize: 17, weight: .regular))
textColor = Asset.Colors.Label.primary.color
case .profileCardName: