Add accessibilityLabel to items in PhotoLibrary
* Refactor PhotoGridItem to be more compile-time safe * Add accessibilityLabel to items in PhotoLibrary * run auto genstrings * fix build issue Co-authored-by: Meher Kasam <meheranandk@gmail.com>
This commit is contained in:
parent
ac5b4ea717
commit
793a1cee45
@ -340,8 +340,8 @@ class RecentPhotoCell: UICollectionViewCell {
|
||||
contentTypeBadgeView?.sizeToFit()
|
||||
}
|
||||
|
||||
private func setMedia(duration: TimeInterval) {
|
||||
guard duration > 0 else {
|
||||
private func setMedia(itemType: PhotoGridItemType) {
|
||||
guard case .video(let duration) = itemType else {
|
||||
durationLabel?.isHidden = true
|
||||
durationLabelBackground?.isHidden = true
|
||||
return
|
||||
@ -398,7 +398,7 @@ class RecentPhotoCell: UICollectionViewCell {
|
||||
self.image = image
|
||||
}
|
||||
|
||||
setMedia(duration: item.duration)
|
||||
setMedia(itemType: item.type)
|
||||
|
||||
switch item.type {
|
||||
case .animated:
|
||||
|
||||
@ -892,7 +892,7 @@ class GalleryGridCellItem: PhotoGridItem {
|
||||
|
||||
var type: PhotoGridItemType {
|
||||
if galleryItem.isVideo {
|
||||
return .video
|
||||
return .video(0) // TODO: return video duration
|
||||
} else if galleryItem.isAnimated {
|
||||
return .animated
|
||||
} else {
|
||||
@ -900,10 +900,7 @@ class GalleryGridCellItem: PhotoGridItem {
|
||||
}
|
||||
}
|
||||
|
||||
var duration: TimeInterval {
|
||||
// TODO: return video duration
|
||||
0
|
||||
}
|
||||
var creationDate: Date? { nil }
|
||||
|
||||
func asyncThumbnail(completion: @escaping (UIImage?) -> Void) -> UIImage? {
|
||||
return galleryItem.thumbnailImage(async: completion)
|
||||
|
||||
@ -40,7 +40,7 @@ class PhotoPickerAssetItem: PhotoGridItem {
|
||||
|
||||
var type: PhotoGridItemType {
|
||||
if asset.mediaType == .video {
|
||||
return .video
|
||||
return .video(asset.duration)
|
||||
} else if asset.playbackStyle == .imageAnimated {
|
||||
return .animated
|
||||
} else {
|
||||
@ -48,10 +48,7 @@ class PhotoPickerAssetItem: PhotoGridItem {
|
||||
}
|
||||
}
|
||||
|
||||
var duration: TimeInterval {
|
||||
guard asset.mediaType == .video else { return 0 }
|
||||
return asset.duration
|
||||
}
|
||||
var creationDate: Date? { asset.creationDate }
|
||||
|
||||
func asyncThumbnail(completion: @escaping (UIImage?) -> Void) -> UIImage? {
|
||||
var syncImageResult: UIImage?
|
||||
|
||||
@ -3,17 +3,31 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
//
|
||||
|
||||
import SignalMessaging
|
||||
import SignalUI
|
||||
import UIKit
|
||||
|
||||
public enum PhotoGridItemType {
|
||||
case photo, animated, video
|
||||
public enum PhotoGridItemType: Equatable {
|
||||
case photo
|
||||
case animated
|
||||
case video(TimeInterval)
|
||||
|
||||
var localizedString: String {
|
||||
switch self {
|
||||
case .photo:
|
||||
return CommonStrings.attachmentTypePhoto
|
||||
case .animated:
|
||||
return CommonStrings.attachmentTypeAnimated
|
||||
case .video(let duration):
|
||||
return "\(CommonStrings.attachmentTypeVideo) \(OWSFormat.localizedDurationString(from: duration))"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public protocol PhotoGridItem: AnyObject {
|
||||
var type: PhotoGridItemType { get }
|
||||
var duration: TimeInterval { get } // proxy to PHAsset.duration, always 0 for non-movie assets
|
||||
func asyncThumbnail(completion: @escaping (UIImage?) -> Void) -> UIImage?
|
||||
var creationDate: Date? { get }
|
||||
}
|
||||
|
||||
public class PhotoGridViewCell: UICollectionViewCell {
|
||||
@ -37,6 +51,29 @@ public class PhotoGridViewCell: UICollectionViewCell {
|
||||
private static let selectedBadgeImage = UIImage(named: "media-composer-checkmark")
|
||||
public var loadingColor = Theme.washColor
|
||||
|
||||
private lazy var todayTimeFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = .current
|
||||
formatter.dateStyle = .none
|
||||
formatter.timeStyle = .short
|
||||
return formatter
|
||||
}()
|
||||
|
||||
private lazy var thisYearDateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = .current
|
||||
formatter.setLocalizedDateFormatFromTemplate("MMMMd")
|
||||
return formatter
|
||||
}()
|
||||
|
||||
private lazy var longDateFormatter: DateFormatter = {
|
||||
let formatter = DateFormatter()
|
||||
formatter.locale = .current
|
||||
formatter.dateStyle = .long
|
||||
formatter.timeStyle = .none
|
||||
return formatter
|
||||
}()
|
||||
|
||||
override public var isSelected: Bool {
|
||||
didSet {
|
||||
updateSelectionState()
|
||||
@ -169,8 +206,8 @@ public class PhotoGridViewCell: UICollectionViewCell {
|
||||
contentTypeBadgeView?.sizeToFit()
|
||||
}
|
||||
|
||||
private func setMedia(duration: TimeInterval) {
|
||||
guard duration > 0 else {
|
||||
private func setMedia(itemType: PhotoGridItemType) {
|
||||
guard case .video(let duration) = itemType else {
|
||||
durationLabel?.isHidden = true
|
||||
durationLabelBackground?.isHidden = true
|
||||
return
|
||||
@ -219,6 +256,17 @@ public class PhotoGridViewCell: UICollectionViewCell {
|
||||
durationLabel.sizeToFit()
|
||||
}
|
||||
|
||||
private func setUpAccessibility(item: PhotoGridItem) {
|
||||
self.isAccessibilityElement = true
|
||||
|
||||
self.accessibilityLabel = [
|
||||
item.type.localizedString,
|
||||
formattedDateString(for: item.creationDate)
|
||||
]
|
||||
.compactMap { $0 }
|
||||
.joined(separator: ", ")
|
||||
}
|
||||
|
||||
public func configure(item: PhotoGridItem) {
|
||||
self.item = item
|
||||
|
||||
@ -244,7 +292,8 @@ public class PhotoGridViewCell: UICollectionViewCell {
|
||||
self.image = image
|
||||
}
|
||||
|
||||
setMedia(duration: item.duration)
|
||||
setMedia(itemType: item.type)
|
||||
setUpAccessibility(item: item)
|
||||
|
||||
switch item.type {
|
||||
case .animated:
|
||||
@ -267,4 +316,21 @@ public class PhotoGridViewCell: UICollectionViewCell {
|
||||
selectedBadgeView.isHidden = true
|
||||
outlineBadgeView.isHidden = true
|
||||
}
|
||||
|
||||
private func formattedDateString(for date: Date?) -> String? {
|
||||
guard let date = date else { return nil }
|
||||
|
||||
let dateIsThisYear = DateUtil.dateIsThisYear(date)
|
||||
let dateIsToday = DateUtil.dateIsToday(date)
|
||||
|
||||
if dateIsToday {
|
||||
return todayTimeFormatter.string(from: date)
|
||||
}
|
||||
|
||||
if dateIsThisYear {
|
||||
return thisYearDateFormatter.string(from: date)
|
||||
}
|
||||
|
||||
return longDateFormatter.string(from: date)
|
||||
}
|
||||
}
|
||||
|
||||
@ -298,6 +298,9 @@
|
||||
/* Alert title when picking a document fails because user picked a directory/bundle */
|
||||
"ATTACHMENT_PICKER_DOCUMENTS_PICKED_DIRECTORY_FAILED_ALERT_TITLE" = "Unsupported File";
|
||||
|
||||
/* Short text label for an animated attachment, used for thread preview and on the lock screen */
|
||||
"ATTACHMENT_TYPE_ANIMATED" = "Animated";
|
||||
|
||||
/* Short text label for a audio attachment, used for thread preview and on the lock screen */
|
||||
"ATTACHMENT_TYPE_AUDIO" = "Audio";
|
||||
|
||||
|
||||
@ -274,6 +274,12 @@ public class CommonStrings: NSObject {
|
||||
comment: "Short text label for a video attachment, used for thread preview and on the lock screen")
|
||||
}
|
||||
|
||||
@objc
|
||||
static public var attachmentTypeAnimated: String {
|
||||
OWSLocalizedString("ATTACHMENT_TYPE_ANIMATED",
|
||||
comment: "Short text label for an animated attachment, used for thread preview and on the lock screen")
|
||||
}
|
||||
|
||||
@objc
|
||||
static public var searchBarPlaceholder: String {
|
||||
OWSLocalizedString("INVITE_FRIENDS_PICKER_SEARCHBAR_PLACEHOLDER", comment: "Search")
|
||||
|
||||
Loading…
Reference in New Issue
Block a user