mirror of
https://github.com/metabolist/metatext.git
synced 2024-11-21 15:50:59 +00:00
Escape unicode in all URLs from API
This commit is contained in:
parent
0ca2bf9653
commit
9552305a78
37 changed files with 136 additions and 107 deletions
|
@ -16,10 +16,10 @@ struct AccountRecord: ContentDatabaseRecord, Hashable {
|
|||
let statusesCount: Int
|
||||
let note: HTML
|
||||
let url: String
|
||||
let avatar: URL
|
||||
let avatarStatic: URL
|
||||
let header: URL
|
||||
let headerStatic: URL
|
||||
let avatar: UnicodeURL
|
||||
let avatarStatic: UnicodeURL
|
||||
let header: UnicodeURL
|
||||
let headerStatic: UnicodeURL
|
||||
let fields: [Account.Field]
|
||||
let emojis: [Emoji]
|
||||
let bot: Bool
|
||||
|
|
|
@ -7,7 +7,7 @@ import Mastodon
|
|||
struct FeaturedTagRecord: ContentDatabaseRecord, Hashable {
|
||||
let id: FeaturedTag.Id
|
||||
let name: String
|
||||
let url: URL
|
||||
let url: UnicodeURL
|
||||
let statusesCount: Int
|
||||
let lastStatusAt: Date
|
||||
let accountId: Account.Id
|
||||
|
|
|
@ -8,8 +8,8 @@ struct IdentityProofRecord: ContentDatabaseRecord, Hashable {
|
|||
let accountId: Account.Id
|
||||
let provider: String
|
||||
let providerUsername: String
|
||||
let profileUrl: URL
|
||||
let proofUrl: URL
|
||||
let profileUrl: UnicodeURL
|
||||
let proofUrl: UnicodeURL
|
||||
let updatedAt: Date
|
||||
}
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@ struct InstanceRecord: ContentDatabaseRecord, Hashable {
|
|||
let invitesEnabled: Bool
|
||||
let urls: Instance.URLs
|
||||
let stats: Instance.Stats
|
||||
let thumbnail: URL?
|
||||
let thumbnail: UnicodeURL?
|
||||
let contactAccountId: Account.Id?
|
||||
let maxTootChars: Int?
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ public extension Identity {
|
|||
|
||||
struct Instance: Codable, Hashable {
|
||||
public let uri: String
|
||||
public let streamingAPI: URL
|
||||
public let streamingAPI: UnicodeURL
|
||||
public let title: String
|
||||
public let thumbnail: URL?
|
||||
public let thumbnail: UnicodeURL?
|
||||
public let version: String
|
||||
public let maxTootChars: Int?
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ public extension Identity {
|
|||
public let username: String
|
||||
public let displayName: String
|
||||
public let url: String
|
||||
public let avatar: URL
|
||||
public let avatarStatic: URL
|
||||
public let header: URL
|
||||
public let headerStatic: URL
|
||||
public let avatar: UnicodeURL
|
||||
public let avatarStatic: UnicodeURL
|
||||
public let header: UnicodeURL
|
||||
public let headerStatic: UnicodeURL
|
||||
public let emojis: [Emoji]
|
||||
public let followRequestCount: Int
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ public extension Identity {
|
|||
return instance?.title ?? url.host ?? url.absoluteString
|
||||
}
|
||||
|
||||
var image: URL? { account?.avatar ?? instance?.thumbnail }
|
||||
var image: URL? { (account?.avatar ?? instance?.thumbnail)?.url }
|
||||
}
|
||||
|
||||
public extension Identity.Preferences {
|
||||
|
|
|
@ -89,15 +89,14 @@ extension CollectionItem {
|
|||
|
||||
private extension Account {
|
||||
func mediaPrefetchURLs(identityContext: IdentityContext) -> Set<URL> {
|
||||
var urls = Set(emojis.compactMap {
|
||||
identityContext.appPreferences.animateCustomEmojis ? $0.url : $0.staticUrl
|
||||
}
|
||||
.compactMap(URL.init(string:)))
|
||||
var urls = Set(emojis.map {
|
||||
(identityContext.appPreferences.animateCustomEmojis ? $0.url : $0.staticUrl).url
|
||||
})
|
||||
|
||||
if identityContext.appPreferences.animateAvatars == .everywhere {
|
||||
urls.insert(avatar)
|
||||
urls.insert(avatar.url)
|
||||
} else {
|
||||
urls.insert(avatarStatic)
|
||||
urls.insert(avatarStatic.url)
|
||||
}
|
||||
|
||||
return urls
|
||||
|
@ -107,10 +106,9 @@ private extension Account {
|
|||
private extension Status {
|
||||
func mediaPrefetchURLs(identityContext: IdentityContext) -> Set<URL> {
|
||||
displayStatus.account.mediaPrefetchURLs(identityContext: identityContext)
|
||||
.union(displayStatus.mediaAttachments.compactMap(\.previewUrl))
|
||||
.union(displayStatus.emojis.compactMap {
|
||||
identityContext.appPreferences.animateCustomEmojis ? $0.url : $0.staticUrl
|
||||
}
|
||||
.compactMap(URL.init(string:)))
|
||||
.union(displayStatus.mediaAttachments.compactMap(\.previewUrl?.url))
|
||||
.union(displayStatus.emojis.map {
|
||||
(identityContext.appPreferences.animateCustomEmojis ? $0.url : $0.staticUrl).url
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,15 +12,12 @@ extension NSMutableAttributedString {
|
|||
|
||||
while let tokenRange = string.range(of: token) {
|
||||
let attachment = AnimatedTextAttachment()
|
||||
let imageURL: URL?
|
||||
let imageURL: URL
|
||||
|
||||
if identityContext.appPreferences.animateCustomEmojis,
|
||||
let urlString = emoji.url {
|
||||
imageURL = URL(stringEscapingPath: urlString)
|
||||
} else if let staticURLString = emoji.staticUrl {
|
||||
imageURL = URL(stringEscapingPath: staticURLString)
|
||||
if identityContext.appPreferences.animateCustomEmojis {
|
||||
imageURL = emoji.url.url
|
||||
} else {
|
||||
imageURL = nil
|
||||
imageURL = emoji.staticUrl.url
|
||||
}
|
||||
|
||||
attachment.imageView.sd_setImage(with: imageURL) { image, _, _, _ in
|
||||
|
|
|
@ -14,10 +14,10 @@ public final class Account: Codable, Identifiable {
|
|||
public let statusesCount: Int
|
||||
public let note: HTML
|
||||
public let url: String
|
||||
public let avatar: URL
|
||||
public let avatarStatic: URL
|
||||
public let header: URL
|
||||
public let headerStatic: URL
|
||||
public let avatar: UnicodeURL
|
||||
public let avatarStatic: UnicodeURL
|
||||
public let header: UnicodeURL
|
||||
public let headerStatic: UnicodeURL
|
||||
public let fields: [Field]
|
||||
public let emojis: [Emoji]
|
||||
@DecodableDefault.False public private(set) var bot: Bool
|
||||
|
@ -36,10 +36,10 @@ public final class Account: Codable, Identifiable {
|
|||
statusesCount: Int,
|
||||
note: HTML,
|
||||
url: String,
|
||||
avatar: URL,
|
||||
avatarStatic: URL,
|
||||
header: URL,
|
||||
headerStatic: URL,
|
||||
avatar: UnicodeURL,
|
||||
avatarStatic: UnicodeURL,
|
||||
header: UnicodeURL,
|
||||
headerStatic: UnicodeURL,
|
||||
fields: [Account.Field],
|
||||
emojis: [Emoji],
|
||||
bot: Bool,
|
||||
|
|
|
@ -6,6 +6,6 @@ public struct AnnouncementReaction: Codable, Hashable {
|
|||
public let name: String
|
||||
public let count: Int
|
||||
public let me: Bool
|
||||
public let url: URL?
|
||||
public let staticUrl: URL?
|
||||
public let url: UnicodeURL?
|
||||
public let staticUrl: UnicodeURL?
|
||||
}
|
||||
|
|
|
@ -34,9 +34,9 @@ public struct Attachment: Codable, Hashable {
|
|||
|
||||
public let id: Id
|
||||
public let type: AttachmentType
|
||||
public let url: URL
|
||||
public let remoteUrl: URL?
|
||||
public let previewUrl: URL?
|
||||
public let url: UnicodeURL
|
||||
public let remoteUrl: UnicodeURL?
|
||||
public let previewUrl: UnicodeURL?
|
||||
public let meta: Meta?
|
||||
public let description: String?
|
||||
public let blurhash: String?
|
||||
|
|
|
@ -9,7 +9,7 @@ public struct Card: Codable, Hashable {
|
|||
public static var unknownCase: Self { .unknown }
|
||||
}
|
||||
|
||||
public let url: URL
|
||||
public let url: UnicodeURL
|
||||
public let title: String
|
||||
public let description: String
|
||||
public let type: CardType
|
||||
|
@ -20,6 +20,6 @@ public struct Card: Codable, Hashable {
|
|||
public let html: String?
|
||||
public let width: Int?
|
||||
public let height: Int?
|
||||
public let image: URL?
|
||||
public let image: UnicodeURL?
|
||||
public let embedUrl: String?
|
||||
}
|
||||
|
|
|
@ -4,8 +4,8 @@ import Foundation
|
|||
|
||||
public struct Emoji: Codable, Hashable {
|
||||
public let shortcode: String
|
||||
public let staticUrl: String?
|
||||
public let url: String?
|
||||
public let staticUrl: UnicodeURL
|
||||
public let url: UnicodeURL
|
||||
public let visibleInPicker: Bool
|
||||
public let category: String?
|
||||
}
|
||||
|
|
|
@ -5,11 +5,11 @@ import Foundation
|
|||
public struct FeaturedTag: Codable, Hashable {
|
||||
public let id: Id
|
||||
public let name: String
|
||||
public let url: URL
|
||||
public let url: UnicodeURL
|
||||
public let statusesCount: Int
|
||||
public let lastStatusAt: Date
|
||||
|
||||
public init(id: FeaturedTag.Id, name: String, url: URL, statusesCount: Int, lastStatusAt: Date) {
|
||||
public init(id: FeaturedTag.Id, name: String, url: UnicodeURL, statusesCount: Int, lastStatusAt: Date) {
|
||||
self.id = id
|
||||
self.name = name
|
||||
self.url = url
|
||||
|
|
|
@ -5,11 +5,15 @@ import Foundation
|
|||
public struct IdentityProof: Codable, Hashable {
|
||||
public let provider: String
|
||||
public let providerUsername: String
|
||||
public let profileUrl: URL
|
||||
public let proofUrl: URL
|
||||
public let profileUrl: UnicodeURL
|
||||
public let proofUrl: UnicodeURL
|
||||
public let updatedAt: Date
|
||||
|
||||
public init(provider: String, providerUsername: String, profileUrl: URL, proofUrl: URL, updatedAt: Date) {
|
||||
public init(provider: String,
|
||||
providerUsername: String,
|
||||
profileUrl: UnicodeURL,
|
||||
proofUrl: UnicodeURL,
|
||||
updatedAt: Date) {
|
||||
self.provider = provider
|
||||
self.providerUsername = providerUsername
|
||||
self.profileUrl = profileUrl
|
||||
|
|
|
@ -4,7 +4,7 @@ import Foundation
|
|||
|
||||
public struct Instance: Codable, Hashable {
|
||||
public struct URLs: Codable, Hashable {
|
||||
public let streamingApi: URL
|
||||
public let streamingApi: UnicodeURL
|
||||
}
|
||||
|
||||
public struct Stats: Codable, Hashable {
|
||||
|
@ -25,7 +25,7 @@ public struct Instance: Codable, Hashable {
|
|||
@DecodableDefault.False public private(set) var invitesEnabled: Bool
|
||||
public let urls: URLs
|
||||
public let stats: Stats
|
||||
public let thumbnail: URL?
|
||||
public let thumbnail: UnicodeURL?
|
||||
public let contactAccount: Account?
|
||||
public let maxTootChars: Int?
|
||||
|
||||
|
@ -37,7 +37,7 @@ public struct Instance: Codable, Hashable {
|
|||
version: String,
|
||||
urls: Instance.URLs,
|
||||
stats: Instance.Stats,
|
||||
thumbnail: URL?,
|
||||
thumbnail: UnicodeURL?,
|
||||
contactAccount: Account?,
|
||||
maxTootChars: Int?) {
|
||||
self.uri = uri
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
import Foundation
|
||||
|
||||
public struct Mention: Codable, Hashable {
|
||||
public let url: URL
|
||||
public let url: UnicodeURL
|
||||
public let username: String
|
||||
public let acct: String
|
||||
public let id: Account.Id
|
||||
|
|
|
@ -6,7 +6,7 @@ public struct PushNotification: Codable {
|
|||
public let accessToken: String
|
||||
public let body: String
|
||||
public let title: String
|
||||
public let icon: URL
|
||||
public let icon: UnicodeURL
|
||||
public let notificationId: Int
|
||||
public let notificationType: MastodonNotification.NotificationType
|
||||
public let preferredLocale: String
|
||||
|
|
|
@ -13,7 +13,7 @@ public struct PushSubscription: Codable {
|
|||
@DecodableDefault.True public var status: Bool
|
||||
}
|
||||
|
||||
public let endpoint: URL
|
||||
public let endpoint: UnicodeURL
|
||||
public let alerts: Alerts
|
||||
public let serverKey: String
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import Foundation
|
|||
|
||||
public struct Tag: Codable, Hashable {
|
||||
public let name: String
|
||||
public let url: URL
|
||||
public let url: UnicodeURL
|
||||
public let history: [History]?
|
||||
}
|
||||
|
||||
|
|
37
Mastodon/Sources/Mastodon/Entities/UnicodeURL.swift
Normal file
37
Mastodon/Sources/Mastodon/Entities/UnicodeURL.swift
Normal file
|
@ -0,0 +1,37 @@
|
|||
// Copyright © 2021 Metabolist. All rights reserved.
|
||||
|
||||
import Foundation
|
||||
|
||||
public struct UnicodeURL: Hashable {
|
||||
public let raw: String
|
||||
public let url: URL
|
||||
}
|
||||
|
||||
extension UnicodeURL: Codable {
|
||||
public init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
|
||||
raw = try container.decode(String.self)
|
||||
|
||||
if let url = URL(string: raw) {
|
||||
self.url = url
|
||||
} else if let escaped = raw.addingPercentEncoding(withAllowedCharacters: .urlPathAllowed) {
|
||||
let colonUnescaped = escaped.replacingOccurrences(
|
||||
of: "%3A",
|
||||
with: ":",
|
||||
range: escaped.range(of: "%3A"))
|
||||
|
||||
guard let url = URL(string: colonUnescaped) else { throw URLError(.badURL) }
|
||||
|
||||
self.url = url
|
||||
} else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
}
|
||||
|
||||
public func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
|
||||
try container.encode(raw)
|
||||
}
|
||||
}
|
|
@ -54,7 +54,7 @@ final class NotificationService: UNNotificationServiceExtension {
|
|||
bestAttemptContent.subtitle = handle
|
||||
}
|
||||
|
||||
Self.attachment(imageURL: pushNotification.icon)
|
||||
Self.attachment(imageURL: pushNotification.icon.url)
|
||||
.map { [$0] }
|
||||
.replaceError(with: [])
|
||||
.handleEvents(receiveOutput: { bestAttemptContent.attachments = $0 })
|
||||
|
|
|
@ -122,7 +122,7 @@ public extension NavigationService {
|
|||
|
||||
private extension NavigationService {
|
||||
func tag(url: URL) -> String? {
|
||||
if status?.tags.first(where: { $0.url.path.lowercased() == url.path.lowercased() }) != nil {
|
||||
if status?.tags.first(where: { $0.url.url.path.lowercased() == url.path.lowercased() }) != nil {
|
||||
return url.lastPathComponent
|
||||
} else if
|
||||
mastodonAPIClient.instanceURL.host == url.host {
|
||||
|
@ -133,7 +133,9 @@ private extension NavigationService {
|
|||
}
|
||||
|
||||
func accountId(url: URL) -> String? {
|
||||
if let mentionId = status?.mentions.first(where: { $0.url.path.lowercased() == url.path.lowercased() })?.id {
|
||||
if let mentionId = status?.mentions.first(where: {
|
||||
$0.url.url.path.lowercased() == url.path.lowercased()
|
||||
})?.id {
|
||||
return mentionId
|
||||
} else if
|
||||
mastodonAPIClient.instanceURL.host == url.host {
|
||||
|
|
|
@ -262,7 +262,7 @@ private extension AddIdentityViewController {
|
|||
if let instance = instance {
|
||||
self.instanceTitleLabel.text = instance.title
|
||||
self.instanceURLLabel.text = instance.uri
|
||||
self.instanceImageView.sd_setImage(with: instance.thumbnail)
|
||||
self.instanceImageView.sd_setImage(with: instance.thumbnail?.url)
|
||||
self.instanceStackView.isHidden_stackViewSafe = false
|
||||
|
||||
if instance.registrations {
|
||||
|
|
|
@ -52,9 +52,9 @@ final class EditAttachmentViewController: UIViewController {
|
|||
let player: AVPlayer
|
||||
|
||||
if viewModel.attachment.type == .video {
|
||||
player = PlayerCache.shared.player(url: viewModel.attachment.url)
|
||||
player = PlayerCache.shared.player(url: viewModel.attachment.url.url)
|
||||
} else {
|
||||
player = AVPlayer(url: viewModel.attachment.url)
|
||||
player = AVPlayer(url: viewModel.attachment.url.url)
|
||||
}
|
||||
|
||||
player.isMuted = false
|
||||
|
@ -188,7 +188,7 @@ private extension EditAttachmentViewController {
|
|||
|
||||
func detectTextFromPicture() {
|
||||
SDWebImageManager.shared.loadImage(
|
||||
with: viewModel.attachment.url,
|
||||
with: viewModel.attachment.url.url,
|
||||
options: [],
|
||||
progress: nil) { image, _, _, _, _, _ in
|
||||
guard let cgImage = image?.cgImage else { return }
|
||||
|
|
|
@ -127,7 +127,7 @@ final class ImageViewController: UIViewController {
|
|||
playerView.isHidden = true
|
||||
|
||||
let placeholderImage: UIImage?
|
||||
let cachedImageKey = viewModel.attachment.previewUrl?.absoluteString
|
||||
let cachedImageKey = viewModel.attachment.previewUrl?.url.absoluteString
|
||||
let cachedImage = SDImageCache.shared.imageFromCache(forKey: cachedImageKey)
|
||||
|
||||
if cachedImage != nil {
|
||||
|
@ -139,7 +139,7 @@ final class ImageViewController: UIViewController {
|
|||
placeholderImage = nil
|
||||
}
|
||||
|
||||
imageView.sd_setImage(with: viewModel.attachment.url,
|
||||
imageView.sd_setImage(with: viewModel.attachment.url.url,
|
||||
placeholderImage: placeholderImage) { _, error, _, _ in
|
||||
if error != nil {
|
||||
let alertItem = AlertItem(error: ImageError.unableToLoad)
|
||||
|
@ -150,7 +150,7 @@ final class ImageViewController: UIViewController {
|
|||
case .gifv:
|
||||
playerView.tag = viewModel.tag
|
||||
imageView.isHidden = true
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url)
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url.url)
|
||||
|
||||
player.isMuted = true
|
||||
|
||||
|
|
|
@ -589,9 +589,9 @@ private extension TableViewController {
|
|||
let player: AVPlayer
|
||||
|
||||
if attachmentViewModel.attachment.type == .video {
|
||||
player = PlayerCache.shared.player(url: attachmentViewModel.attachment.url)
|
||||
player = PlayerCache.shared.player(url: attachmentViewModel.attachment.url.url)
|
||||
} else {
|
||||
player = AVPlayer(url: attachmentViewModel.attachment.url)
|
||||
player = AVPlayer(url: attachmentViewModel.attachment.url.url)
|
||||
}
|
||||
|
||||
playerViewController.delegate = self
|
||||
|
|
|
@ -29,9 +29,9 @@ public extension AccountViewModel {
|
|||
|
||||
var headerURL: URL {
|
||||
if identityContext.appPreferences.animateHeaders {
|
||||
return accountService.account.header
|
||||
return accountService.account.header.url
|
||||
} else {
|
||||
return accountService.account.headerStatic
|
||||
return accountService.account.headerStatic.url
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -66,9 +66,9 @@ public extension AccountViewModel {
|
|||
func avatarURL(profile: Bool = false) -> URL {
|
||||
if identityContext.appPreferences.animateAvatars == .everywhere
|
||||
|| (identityContext.appPreferences.animateAvatars == .profiles && profile) {
|
||||
return accountService.account.avatar
|
||||
return accountService.account.avatar.url
|
||||
} else {
|
||||
return accountService.account.avatarStatic
|
||||
return accountService.account.avatarStatic.url
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -12,11 +12,11 @@ public struct CardViewModel {
|
|||
}
|
||||
|
||||
public extension CardViewModel {
|
||||
var url: URL { card.url }
|
||||
var url: URL { card.url.url }
|
||||
|
||||
var title: String { card.title }
|
||||
|
||||
var description: String { card.description }
|
||||
|
||||
var imageURL: URL? { card.image }
|
||||
var imageURL: URL? { card.image?.url }
|
||||
}
|
||||
|
|
|
@ -18,13 +18,13 @@ public extension EmojiViewModel {
|
|||
|
||||
var system: Bool { emoji.system }
|
||||
|
||||
var url: String? {
|
||||
var url: URL? {
|
||||
guard case let .custom(emoji, _) = emoji else { return nil }
|
||||
|
||||
if identityContext.appPreferences.animateCustomEmojis {
|
||||
return emoji.url
|
||||
return emoji.url.url
|
||||
} else {
|
||||
return emoji.staticUrl
|
||||
return emoji.staticUrl.url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,17 +83,17 @@ public extension StatusViewModel {
|
|||
|
||||
var avatarURL: URL {
|
||||
if identityContext.appPreferences.animateAvatars == .everywhere {
|
||||
return statusService.status.displayStatus.account.avatar
|
||||
return statusService.status.displayStatus.account.avatar.url
|
||||
} else {
|
||||
return statusService.status.displayStatus.account.avatarStatic
|
||||
return statusService.status.displayStatus.account.avatarStatic.url
|
||||
}
|
||||
}
|
||||
|
||||
var rebloggerAvatarURL: URL {
|
||||
if identityContext.appPreferences.animateAvatars == .everywhere {
|
||||
return statusService.status.account.avatar
|
||||
return statusService.status.account.avatar.url
|
||||
} else {
|
||||
return statusService.status.account.avatarStatic
|
||||
return statusService.status.account.avatarStatic.url
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -351,7 +351,7 @@ public extension StatusViewModel {
|
|||
|
||||
func attachmentSelected(viewModel: AttachmentViewModel) {
|
||||
if viewModel.attachment.type == .unknown, let remoteUrl = viewModel.attachment.remoteUrl {
|
||||
urlSelected(remoteUrl)
|
||||
urlSelected(remoteUrl.url)
|
||||
} else {
|
||||
eventsSubject.send(Just(.attachment(viewModel, self)).setFailureType(to: Error.self).eraseToAnyPublisher())
|
||||
}
|
||||
|
|
|
@ -64,7 +64,7 @@ final class AttachmentView: UIView {
|
|||
|
||||
extension AttachmentView {
|
||||
func play() {
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url)
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url.url)
|
||||
|
||||
playerCancellable = NotificationCenter.default.publisher(
|
||||
for: .AVPlayerItemDidPlayToEndTime,
|
||||
|
@ -180,7 +180,7 @@ private extension AttachmentView {
|
|||
}
|
||||
|
||||
imageView.sd_setImage(
|
||||
with: viewModel.attachment.previewUrl,
|
||||
with: viewModel.attachment.previewUrl?.url,
|
||||
placeholderImage: placeholderImage) { [weak self] _, _, _, _ in
|
||||
self?.layoutSubviews()
|
||||
}
|
||||
|
|
|
@ -199,7 +199,7 @@ private extension CompositionView {
|
|||
? $0.identity.account?.avatar
|
||||
: $0.identity.account?.avatarStatic
|
||||
|
||||
self.avatarImageView.sd_setImage(with: avatarURL)
|
||||
self.avatarImageView.sd_setImage(with: avatarURL?.url)
|
||||
self.changeIdentityButton.accessibilityLabel = $0.identity.handle
|
||||
self.changeIdentityButton.accessibilityHint =
|
||||
NSLocalizedString("compose.change-identity-button.accessibility-hint", comment: "")
|
||||
|
|
|
@ -76,16 +76,7 @@ private extension EmojiView {
|
|||
emojiLabel.isHidden = true
|
||||
emojiLabel.text = nil
|
||||
imageView.isHidden = false
|
||||
|
||||
let url: URL?
|
||||
|
||||
if let urlString = emojiConfiguration.viewModel.url {
|
||||
url = URL(stringEscapingPath: urlString)
|
||||
} else {
|
||||
url = nil
|
||||
}
|
||||
|
||||
imageView.sd_setImage(with: url)
|
||||
imageView.sd_setImage(with: emojiConfiguration.viewModel.url)
|
||||
}
|
||||
|
||||
accessibilityLabel = emojiConfiguration.viewModel.name
|
||||
|
|
|
@ -73,7 +73,7 @@ private extension AutocompleteItemView {
|
|||
switch autocompleteItemConfiguration.item {
|
||||
case let .account(account):
|
||||
let appPreferences = autocompleteItemConfiguration.identityContext.appPreferences
|
||||
let avatarURL = appPreferences.animateAvatars == .everywhere ? account.avatar : account.avatarStatic
|
||||
let avatarURL = (appPreferences.animateAvatars == .everywhere ? account.avatar : account.avatarStatic).url
|
||||
|
||||
imageView.sd_setImage(with: avatarURL)
|
||||
imageView.isHidden = false
|
||||
|
|
|
@ -77,7 +77,7 @@ private extension InstanceView {
|
|||
func applyInstanceConfiguration() {
|
||||
let viewModel = instanceConfiguration.viewModel
|
||||
|
||||
imageView.sd_setImage(with: viewModel.instance.thumbnail)
|
||||
imageView.sd_setImage(with: viewModel.instance.thumbnail?.url)
|
||||
imageView.autoPlayAnimatedImage = !UIAccessibility.isReduceMotionEnabled
|
||||
|
||||
titleLabel.text = viewModel.instance.title
|
||||
|
|
|
@ -138,7 +138,7 @@ private extension EditThumbnailView {
|
|||
previewImageView.contentMode = .scaleAspectFill
|
||||
previewImageView.clipsToBounds = true
|
||||
previewImageView.layer.cornerRadius = .defaultCornerRadius
|
||||
previewImageView.sd_setImage(with: viewModel.attachment.previewUrl)
|
||||
previewImageView.sd_setImage(with: viewModel.attachment.previewUrl?.url)
|
||||
|
||||
switch viewModel.attachment.type {
|
||||
case .image:
|
||||
|
@ -151,10 +151,10 @@ private extension EditThumbnailView {
|
|||
placeholderImage = nil
|
||||
}
|
||||
|
||||
imageView.sd_setImage(with: viewModel.attachment.previewUrl, placeholderImage: placeholderImage)
|
||||
imageView.sd_setImage(with: viewModel.attachment.previewUrl?.url, placeholderImage: placeholderImage)
|
||||
case .gifv:
|
||||
imageView.isHidden = true
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url)
|
||||
let player = PlayerCache.shared.player(url: viewModel.attachment.url.url)
|
||||
|
||||
player.isMuted = true
|
||||
|
||||
|
|
|
@ -69,7 +69,7 @@ private extension SecondaryNavigationTitleView {
|
|||
? viewModel.identityContext.identity.account?.avatar
|
||||
: viewModel.identityContext.identity.account?.avatarStatic
|
||||
|
||||
avatarImageView.sd_setImage(with: avatarURL)
|
||||
avatarImageView.sd_setImage(with: avatarURL?.url)
|
||||
|
||||
if let displayName = viewModel.identityContext.identity.account?.displayName,
|
||||
!displayName.isEmpty {
|
||||
|
|
Loading…
Reference in a new issue