forked from home-assistant/iOS
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathImageAttachmentViewController.swift
109 lines (91 loc) · 3.52 KB
/
ImageAttachmentViewController.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
import MobileCoreServices
import PromiseKit
import Shared
import UIKit
import UserNotifications
import UserNotificationsUI
class ImageAttachmentViewController: UIViewController, NotificationCategory {
let attachmentURL: URL
let needsEndSecurityScoped: Bool
let image: UIImage
let imageView = with(UIImageView()) {
$0.contentMode = .scaleAspectFit
}
required init(notification: UNNotification, attachmentURL: URL?) throws {
guard let attachmentURL = attachmentURL else {
throw ImageAttachmentError.noAttachment
}
self.needsEndSecurityScoped = attachmentURL.startAccessingSecurityScopedResource()
// rather than hard-coding an acceptable list of UTTypes it's probably easier to just try decoding
// https://developer.apple.com/documentation/usernotifications/unnotificationattachment
// has the full list of what is advertised - at time of writing (iOS 14.5) it's jpeg, gif and png
// but iOS 14 also supports webp, so who knows if it'll be added silently or not
guard let image = UIImage(contentsOfFile: attachmentURL.path) else {
attachmentURL.stopAccessingSecurityScopedResource()
throw ImageAttachmentError.imageDecodeFailure
}
self.image = image
self.attachmentURL = attachmentURL
super.init(nibName: nil, bundle: nil)
}
@available(*, unavailable)
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
if needsEndSecurityScoped {
attachmentURL.stopAccessingSecurityScopedResource()
}
}
enum ImageAttachmentError: Error {
case noAttachment
case notImage
case imageDecodeFailure
}
private var aspectRatioConstraint: NSLayoutConstraint? {
willSet {
aspectRatioConstraint?.isActive = false
}
didSet {
aspectRatioConstraint?.isActive = true
}
}
private var lastAttachmentURL: URL? {
didSet {
oldValue?.stopAccessingSecurityScopedResource()
}
}
func start() -> Promise<Void> {
imageView.image = image
lastAttachmentURL = attachmentURL
aspectRatioConstraint = NSLayoutConstraint.aspectRatioConstraint(on: imageView, size: image.size)
return .value(())
}
override func loadView() {
class UnanimatingView: UIView {
override func layoutSubviews() {
// avoids the image view sizing up from nothing when initially displaying
// since we don't control our own view's expansion, we need to disable animation at our level
UIView.performWithoutAnimation {
super.layoutSubviews()
}
}
}
view = UnanimatingView()
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(imageView)
imageView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
imageView.topAnchor.constraint(equalTo: view.topAnchor),
imageView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
imageView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
imageView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
])
}
var mediaPlayPauseButtonType: UNNotificationContentExtensionMediaPlayPauseButtonType { .none }
var mediaPlayPauseButtonFrame: CGRect?
func mediaPlay() {}
func mediaPause() {}
}