Compare commits
5 Commits
e76b719c6a
...
17f15db32d
Author | SHA1 | Date |
---|---|---|
Shadowfacts | 17f15db32d | |
Shadowfacts | 1a11dd2a69 | |
Shadowfacts | b5fa0bceab | |
Shadowfacts | c224d11417 | |
Shadowfacts | bebf47f05c |
|
@ -88,11 +88,16 @@ class MastodonController {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getOwnInstance() {
|
func getOwnInstance(completion: ((Instance) -> Void)? = nil) {
|
||||||
|
if let instance = self.instance {
|
||||||
|
completion?(instance)
|
||||||
|
} else {
|
||||||
let request = Client.getInstance()
|
let request = Client.getInstance()
|
||||||
run(request) { (response) in
|
run(request) { (response) in
|
||||||
guard case let .success(instance, _) = response else { fatalError() }
|
guard case let .success(instance, _) = response else { fatalError() }
|
||||||
self.instance = instance
|
self.instance = instance
|
||||||
|
completion?(instance)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,8 @@ final class CompositionAttachment: NSObject, Codable {
|
||||||
}
|
}
|
||||||
|
|
||||||
private let imageType = kUTTypeImage as String
|
private let imageType = kUTTypeImage as String
|
||||||
|
private let mp4Type = kUTTypeMPEG4 as String
|
||||||
|
private let quickTimeType = kUTTypeQuickTimeMovie as String
|
||||||
private let dataType = kUTTypeData as String
|
private let dataType = kUTTypeData as String
|
||||||
|
|
||||||
extension CompositionAttachment: NSItemProviderWriting {
|
extension CompositionAttachment: NSItemProviderWriting {
|
||||||
|
@ -61,7 +63,10 @@ extension CompositionAttachment: NSItemProviderWriting {
|
||||||
|
|
||||||
extension CompositionAttachment: NSItemProviderReading {
|
extension CompositionAttachment: NSItemProviderReading {
|
||||||
static var readableTypeIdentifiersForItemProvider: [String] {
|
static var readableTypeIdentifiersForItemProvider: [String] {
|
||||||
[typeIdentifier] + UIImage.readableTypeIdentifiersForItemProvider + NSURL.readableTypeIdentifiersForItemProvider
|
// todo: is there a better way of handling movies than manually adding all possible UTI types?
|
||||||
|
// just using kUTTypeMovie doesn't work, because we need the actually type in order to get the file extension
|
||||||
|
// without the file extension, getting the thumbnail and exporting the video for attachment upload fails
|
||||||
|
[typeIdentifier] + UIImage.readableTypeIdentifiersForItemProvider + [mp4Type, quickTimeType] + NSURL.readableTypeIdentifiersForItemProvider
|
||||||
}
|
}
|
||||||
|
|
||||||
static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> Self {
|
static func object(withItemProviderData data: Data, typeIdentifier: String) throws -> Self {
|
||||||
|
@ -69,6 +74,13 @@ extension CompositionAttachment: NSItemProviderReading {
|
||||||
return try PropertyListDecoder().decode(Self.self, from: data)
|
return try PropertyListDecoder().decode(Self.self, from: data)
|
||||||
} else if UIImage.readableTypeIdentifiersForItemProvider.contains(typeIdentifier), let image = try? UIImage.object(withItemProviderData: data, typeIdentifier: typeIdentifier) {
|
} else if UIImage.readableTypeIdentifiersForItemProvider.contains(typeIdentifier), let image = try? UIImage.object(withItemProviderData: data, typeIdentifier: typeIdentifier) {
|
||||||
return CompositionAttachment(data: .image(image)) as! Self
|
return CompositionAttachment(data: .image(image)) as! Self
|
||||||
|
} else if typeIdentifier == mp4Type || typeIdentifier == quickTimeType {
|
||||||
|
let temporaryDirectoryURL = URL(fileURLWithPath: NSTemporaryDirectory(), isDirectory: true)
|
||||||
|
let temporaryFileName = ProcessInfo().globallyUniqueString
|
||||||
|
let fileExt = UTTypeCopyPreferredTagWithClass(typeIdentifier as CFString, kUTTagClassFilenameExtension)!
|
||||||
|
let temporaryFileURL = temporaryDirectoryURL.appendingPathComponent(temporaryFileName).appendingPathExtension(fileExt.takeUnretainedValue() as String)
|
||||||
|
try data.write(to: temporaryFileURL)
|
||||||
|
return CompositionAttachment(data: .video(temporaryFileURL)) as! Self
|
||||||
} else if NSURL.readableTypeIdentifiersForItemProvider.contains(typeIdentifier), let url = try? NSURL.object(withItemProviderData: data, typeIdentifier: typeIdentifier) as URL {
|
} else if NSURL.readableTypeIdentifiersForItemProvider.contains(typeIdentifier), let url = try? NSURL.object(withItemProviderData: data, typeIdentifier: typeIdentifier) as URL {
|
||||||
return CompositionAttachment(data: .video(url)) as! Self
|
return CompositionAttachment(data: .video(url)) as! Self
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -49,6 +49,21 @@ class AssetCollectionViewController: UICollectionViewController {
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
// use the safe area layout guide instead of letting it automatically use the safe area insets
|
||||||
|
// because otherwise, when presented in a popover with the arrow on the left or right side,
|
||||||
|
// the collection view content will be cut off by the width of the arrow because the popover
|
||||||
|
// doesn't respect safe area insets
|
||||||
|
collectionView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
view.safeAreaLayoutGuide.leadingAnchor.constraint(equalTo: collectionView.leadingAnchor),
|
||||||
|
view.safeAreaLayoutGuide.trailingAnchor.constraint(equalTo: collectionView.trailingAnchor),
|
||||||
|
// top ignores safe area because when presented in the sheet container, it simplifies the top content offset
|
||||||
|
view.topAnchor.constraint(equalTo: collectionView.topAnchor),
|
||||||
|
// bottom ignores safe area because we want cells to underflow bottom of the screen on notched iPhones
|
||||||
|
view.bottomAnchor.constraint(equalTo: collectionView.bottomAnchor),
|
||||||
|
])
|
||||||
|
view.backgroundColor = .systemBackground
|
||||||
|
|
||||||
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
|
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(donePressed))
|
||||||
|
|
||||||
collectionView.alwaysBounceVertical = true
|
collectionView.alwaysBounceVertical = true
|
||||||
|
|
|
@ -33,6 +33,8 @@ class AssetPickerSheetContainerViewController: SheetContainerViewController {
|
||||||
|
|
||||||
override func viewDidLoad() {
|
override func viewDidLoad() {
|
||||||
assetPicker.view.layer.cornerRadius = view.bounds.width * 0.02
|
assetPicker.view.layer.cornerRadius = view.bounds.width * 0.02
|
||||||
|
// don't round bottom corners, since they'll always be cut off by the device
|
||||||
|
assetPicker.view.layer.maskedCorners = [.layerMinXMinYCorner, .layerMaxXMinYCorner]
|
||||||
|
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,6 +108,10 @@ class ComposeAttachmentsViewController: UITableViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
override func canPaste(_ itemProviders: [NSItemProvider]) -> Bool {
|
override func canPaste(_ itemProviders: [NSItemProvider]) -> Bool {
|
||||||
|
guard itemProviders.allSatisfy({ $0.canLoadObject(ofClass: CompositionAttachment.self) }) else {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
switch mastodonController.instance.instanceType {
|
switch mastodonController.instance.instanceType {
|
||||||
case .pleroma:
|
case .pleroma:
|
||||||
return true
|
return true
|
||||||
|
@ -299,10 +303,20 @@ class ComposeAttachmentsViewController: UITableViewController {
|
||||||
// MARK: Interaction
|
// MARK: Interaction
|
||||||
|
|
||||||
func addAttachmentPressed() {
|
func addAttachmentPressed() {
|
||||||
|
if traitCollection.horizontalSizeClass == .compact {
|
||||||
let sheetContainer = AssetPickerSheetContainerViewController()
|
let sheetContainer = AssetPickerSheetContainerViewController()
|
||||||
sheetContainer.assetPicker.assetPickerDelegate = self
|
sheetContainer.assetPicker.assetPickerDelegate = self
|
||||||
present(sheetContainer, animated: true)
|
present(sheetContainer, animated: true)
|
||||||
//setOverrideTraitCollection(UITraitCollection(userInterfaceLevel: .elevated), forChild: sheetContainer)
|
} else {
|
||||||
|
let picker = AssetPickerViewController()
|
||||||
|
picker.assetPickerDelegate = self
|
||||||
|
picker.overrideUserInterfaceStyle = .dark
|
||||||
|
picker.modalPresentationStyle = .popover
|
||||||
|
present(picker, animated: true)
|
||||||
|
if let presentationController = picker.presentationController as? UIPopoverPresentationController {
|
||||||
|
presentationController.sourceView = tableView.cellForRow(at: IndexPath(row: 0, section: 1))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,8 +137,14 @@ class ComposeViewController: UIViewController {
|
||||||
|
|
||||||
// we have to set the font here, because the monospaced digit font is not available in IB
|
// we have to set the font here, because the monospaced digit font is not available in IB
|
||||||
charactersRemainingLabel.font = .monospacedDigitSystemFont(ofSize: 17, weight: .regular)
|
charactersRemainingLabel.font = .monospacedDigitSystemFont(ofSize: 17, weight: .regular)
|
||||||
updateCharactersRemaining()
|
|
||||||
updatePlaceholder()
|
updatePlaceholder()
|
||||||
|
// if the compose screen is opened via the home screen shortcut and app isn't running,
|
||||||
|
// the msatodon instance may not have been loaded yet
|
||||||
|
mastodonController.getOwnInstance { (_) in
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
self.updateCharactersRemaining()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
composeAttachmentsViewController = ComposeAttachmentsViewController(attachments: currentDraft?.attachments ?? [], mastodonController: mastodonController)
|
composeAttachmentsViewController = ComposeAttachmentsViewController(attachments: currentDraft?.attachments ?? [], mastodonController: mastodonController)
|
||||||
composeRequiresAttachmentDescriptionsDidChange()
|
composeRequiresAttachmentDescriptionsDidChange()
|
||||||
|
@ -266,7 +272,7 @@ class ComposeViewController: UIViewController {
|
||||||
func updateCharactersRemaining() {
|
func updateCharactersRemaining() {
|
||||||
let count = CharacterCounter.count(text: statusTextView.text)
|
let count = CharacterCounter.count(text: statusTextView.text)
|
||||||
let cwCount = contentWarningEnabled ? (contentWarningTextField.text?.count ?? 0) : 0
|
let cwCount = contentWarningEnabled ? (contentWarningTextField.text?.count ?? 0) : 0
|
||||||
let remaining = (mastodonController.instance.maxStatusCharacters ?? 500) - count - cwCount
|
let remaining = (mastodonController.instance?.maxStatusCharacters ?? 500) - count - cwCount
|
||||||
if remaining < 0 {
|
if remaining < 0 {
|
||||||
charactersRemainingLabel.textColor = .red
|
charactersRemainingLabel.textColor = .red
|
||||||
compositionState.formUnion(.tooManyCharacters)
|
compositionState.formUnion(.tooManyCharacters)
|
||||||
|
|
Loading…
Reference in New Issue