This commit is contained in:
Justin Mazzocchi 2021-01-01 15:31:39 -08:00
parent 3b0f0bf82f
commit 5ae1d9be9a
No known key found for this signature in database
GPG Key ID: E223E6937AAFB01C
6 changed files with 116 additions and 10 deletions

View File

@ -34,6 +34,9 @@
"attachment.sensitive-content" = "Sensitive content";
"attachment.media-hidden" = "Media hidden";
"bookmarks" = "Bookmarks";
"camera-access.title" = "Camera access needed";
"camera-access.description" = "Open system settings to allow camera access";
"camera-access.open-system-settings" = "Open system settings";
"cancel" = "Cancel";
"error" = "Error";
"favorites" = "Favorites";

View File

@ -19,11 +19,15 @@
D01F41D924F880C400D55A2D /* TouchFallthroughTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41D624F880C400D55A2D /* TouchFallthroughTextView.swift */; };
D01F41E424F8889700D55A2D /* StatusAttachmentsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01F41E224F8889700D55A2D /* StatusAttachmentsView.swift */; };
D02E1F95250B13210071AD56 /* SafariView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D02E1F94250B13210071AD56 /* SafariView.swift */; };
D036768E2593E6DE005DF15A /* Status+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0849C7E25903C4900A5EBCC /* Status+Extensions.swift */; };
D036AA02254B6101009094DF /* NotificationListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D036AA01254B6101009094DF /* NotificationListCell.swift */; };
D036AA07254B6118009094DF /* NotificationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D036AA06254B6118009094DF /* NotificationView.swift */; };
D036AA0C254B612B009094DF /* NotificationContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D036AA0B254B612B009094DF /* NotificationContentConfiguration.swift */; };
D036AA17254CA824009094DF /* StatusBodyView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D036AA16254CA823009094DF /* StatusBodyView.swift */; };
D036EBB3259FE28800EC1CFC /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46C24F76169001EBDBB /* UIColor+Extensions.swift */; };
D036EBB8259FE29800EC1CFC /* Status+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0849C7E25903C4900A5EBCC /* Status+Extensions.swift */; };
D036EBBD259FE2A100EC1CFC /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01C6FAB252024BD003D0300 /* Array+Extensions.swift */; };
D036EBC2259FE2AD00EC1CFC /* UIVIewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E7AD3825870B13005F5E2D /* UIVIewController+Extensions.swift */; };
D036EBC7259FE2B700EC1CFC /* KingfisherOptionsInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */; };
D038273C259EA38F00056E0F /* NewStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC10F259C4F20000B67DF /* NewStatusView.swift */; };
D03B1B2A253818F3008F964B /* MediaPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D03B1B29253818F3008F964B /* MediaPreferencesView.swift */; };
D04226FD2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D04226FC2546AC0B000980A3 /* StartupAndSyncingPreferencesView.swift */; };
@ -61,7 +65,6 @@
D08E52EE257D757100FA2C5F /* CompositionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08E52ED257D757100FA2C5F /* CompositionView.swift */; };
D08E52EF257D757100FA2C5F /* CompositionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D08E52ED257D757100FA2C5F /* CompositionView.swift */; };
D08E52F8257D78BE00FA2C5F /* ViewConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EA59472522B8B600804347 /* ViewConstants.swift */; };
D08E52FD257D78CB00FA2C5F /* UIColor+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46C24F76169001EBDBB /* UIColor+Extensions.swift */; };
D0A1F4F7252E7D4B004435BF /* TableViewDataSource.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A1F4F6252E7D4B004435BF /* TableViewDataSource.swift */; };
D0A7AC7325748BFF00E4E8AB /* ReportStatusView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0A7AC7225748BFF00E4E8AB /* ReportStatusView.swift */; };
D0B32F50250B373600311912 /* RegistrationView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0B32F4F250B373600311912 /* RegistrationView.swift */; };
@ -105,7 +108,6 @@
D0E569DB2529319100FA1D72 /* LoadMoreView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E569DA2529319100FA1D72 /* LoadMoreView.swift */; };
D0E569E0252931B100FA1D72 /* LoadMoreContentConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E569DF252931B100FA1D72 /* LoadMoreContentConfiguration.swift */; };
D0E7AD3925870B13005F5E2D /* UIVIewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E7AD3825870B13005F5E2D /* UIVIewController+Extensions.swift */; };
D0E7AD4225870C79005F5E2D /* UIVIewController+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E7AD3825870B13005F5E2D /* UIVIewController+Extensions.swift */; };
D0E9F9AA258450B300EF503D /* CompositionInputAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E9F9A9258450B300EF503D /* CompositionInputAccessoryView.swift */; };
D0E9F9AB258450B300EF503D /* CompositionInputAccessoryView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0E9F9A9258450B300EF503D /* CompositionInputAccessoryView.swift */; };
D0EA59402522AC8700804347 /* CardView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0EA593F2522AC8700804347 /* CardView.swift */; };
@ -115,9 +117,7 @@
D0F0B126251A90F400942152 /* AccountListCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0B125251A90F400942152 /* AccountListCell.swift */; };
D0F0B12E251A97E400942152 /* TableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0B12D251A97E400942152 /* TableViewController.swift */; };
D0F0B136251AA12700942152 /* CollectionItem+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F0B135251AA12700942152 /* CollectionItem+Extensions.swift */; };
D0F2D4DB257F018300986197 /* Array+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D01C6FAB252024BD003D0300 /* Array+Extensions.swift */; };
D0F2D54025818C4B00986197 /* Kingfisher in Frameworks */ = {isa = PBXBuildFile; productRef = D0F2D53F25818C4B00986197 /* Kingfisher */; };
D0F2D5452581ABAB00986197 /* KingfisherOptionsInfo+Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0C7D46E24F76169001EBDBB /* KingfisherOptionsInfo+Extensions.swift */; };
D0F2D54B2581CF7D00986197 /* VisualEffectBlur.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0F2D54A2581CF7D00986197 /* VisualEffectBlur.swift */; };
D0FCC105259C4E61000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
D0FCC106259C4E62000B67DF /* NewStatusViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D0FCC104259C4E61000B67DF /* NewStatusViewController.swift */; };
@ -859,24 +859,24 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
D036EBC7259FE2B700EC1CFC /* KingfisherOptionsInfo+Extensions.swift in Sources */,
D08E52A6257C61C000FA2C5F /* ShareExtensionNavigationViewController.swift in Sources */,
D08E52D2257C811200FA2C5F /* ShareExtensionError+Extensions.swift in Sources */,
D0E9F9AB258450B300EF503D /* CompositionInputAccessoryView.swift in Sources */,
D0F2D4DB257F018300986197 /* Array+Extensions.swift in Sources */,
D0E7AD4225870C79005F5E2D /* UIVIewController+Extensions.swift in Sources */,
D038273C259EA38F00056E0F /* NewStatusView.swift in Sources */,
D08E52EF257D757100FA2C5F /* CompositionView.swift in Sources */,
D0CE9F88258B076900E3A6B6 /* AttachmentUploadView.swift in Sources */,
D036768E2593E6DE005DF15A /* Status+Extensions.swift in Sources */,
D080413F258D904400AD6139 /* CompositionAttachmentContentConfiguration.swift in Sources */,
D0F2D5452581ABAB00986197 /* KingfisherOptionsInfo+Extensions.swift in Sources */,
D08E52C7257C7AEE00FA2C5F /* ShareErrorViewController.swift in Sources */,
D08E52F8257D78BE00FA2C5F /* ViewConstants.swift in Sources */,
D036EBC2259FE2AD00EC1CFC /* UIVIewController+Extensions.swift in Sources */,
D065966725899E910096AC5D /* CompositionAttachmentsDataSource.swift in Sources */,
D0FCC106259C4E62000B67DF /* NewStatusViewController.swift in Sources */,
D036EBBD259FE2A100EC1CFC /* Array+Extensions.swift in Sources */,
D036EBB3259FE28800EC1CFC /* UIColor+Extensions.swift in Sources */,
D0804134258D902900AD6139 /* CompositionAttachmentView.swift in Sources */,
D08E52FD257D78CB00FA2C5F /* UIColor+Extensions.swift in Sources */,
D065966225899E890096AC5D /* CompositionAttachmentCollectionViewCell.swift in Sources */,
D036EBB8259FE29800EC1CFC /* Status+Extensions.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -1129,6 +1129,7 @@
CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 82HL67AXQ2;
GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
INFOPLIST_FILE = "Share Extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.2;
LD_RUNPATH_SEARCH_PATHS = (
@ -1142,6 +1143,7 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG IS_SHARE_EXTENSION";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
};
@ -1153,6 +1155,7 @@
CODE_SIGN_ENTITLEMENTS = "Share Extension/Share Extension.entitlements";
CODE_SIGN_STYLE = Automatic;
DEVELOPMENT_TEAM = 82HL67AXQ2;
GCC_PREPROCESSOR_DEFINITIONS = "";
INFOPLIST_FILE = "Share Extension/Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 14.2;
LD_RUNPATH_SEARCH_PATHS = (
@ -1166,6 +1169,7 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SUPPORTS_MACCATALYST = YES;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = IS_SHARE_EXTENSION;
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;

View File

@ -2,6 +2,10 @@
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSMicrophoneUsageDescription</key>
<string>Enables Metatext to take videos and add them to your posts.</string>
<key>NSCameraUsageDescription</key>
<string>Enables Metatext to take photos and videos and add them to your posts.</string>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>

View File

@ -1,9 +1,11 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVFoundation
import Combine
import Kingfisher
import PhotosUI
import UIKit
import UniformTypeIdentifiers
import ViewModels
final class NewStatusViewController: UIViewController {
@ -17,6 +19,7 @@ final class NewStatusViewController: UIViewController {
target: nil,
action: nil)
private let mediaSelections = PassthroughSubject<[PHPickerResult], Never>()
private let imagePickerResults = PassthroughSubject<[UIImagePickerController.InfoKey: Any]?, Never>()
private var cancellables = Set<AnyCancellable>()
init(viewModel: NewStatusViewModel) {
@ -82,11 +85,31 @@ extension NewStatusViewController: PHPickerViewControllerDelegate {
}
}
extension NewStatusViewController: UIImagePickerControllerDelegate {
func imagePickerController(_ picker: UIImagePickerController,
didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
imagePickerResults.send(info)
dismiss(animated: true)
}
func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
imagePickerResults.send(nil)
dismiss(animated: true)
}
}
// Required by UIImagePickerController
extension NewStatusViewController: UINavigationControllerDelegate {}
private extension NewStatusViewController {
func handle(event: NewStatusViewModel.Event) {
switch event {
case let .presentMediaPicker(compositionViewModel):
presentMediaPicker(compositionViewModel: compositionViewModel)
case let .presentCamera(compositionViewModel):
#if !IS_SHARE_EXTENSION
presentCamera(compositionViewModel: compositionViewModel)
#endif
}
}
@ -196,6 +219,53 @@ private extension NewStatusViewController {
present(picker, animated: true)
}
#if !IS_SHARE_EXTENSION
func presentCamera(compositionViewModel: CompositionViewModel) {
if AVCaptureDevice.authorizationStatus(for: .video) == .denied {
let alertController = UIAlertController(
title: NSLocalizedString("camera-access.title", comment: ""),
message: NSLocalizedString("camera-access.description", comment: ""),
preferredStyle: .alert)
let openSystemSettingsAction = UIAlertAction(
title: NSLocalizedString("camera-access.open-system-settings", comment: ""),
style: .default) { _ in
guard let settingsUrl = URL(string: UIApplication.openSettingsURLString) else { return }
UIApplication.shared.open(settingsUrl)
}
let cancelAction = UIAlertAction(title: NSLocalizedString("cancel", comment: ""), style: .cancel) { _ in }
alertController.addAction(openSystemSettingsAction)
alertController.addAction(cancelAction)
present(alertController, animated: true)
return
}
imagePickerResults.first().sink { [weak self] in
guard let self = self, let info = $0 else { return }
if let url = info[.mediaURL] as? URL, let itemProvider = NSItemProvider(contentsOf: url) {
self.viewModel.attach(itemProvider: itemProvider, to: compositionViewModel)
} else if let image = info[.editedImage] as? UIImage ?? info[.originalImage] as? UIImage {
self.viewModel.attach(itemProvider: NSItemProvider(object: image), to: compositionViewModel)
}
}
.store(in: &cancellables)
let picker = UIImagePickerController()
picker.sourceType = .camera
picker.allowsEditing = true
picker.mediaTypes = [UTType.image.description, UTType.movie.description]
picker.modalPresentationStyle = .overFullScreen
picker.delegate = self
present(picker, animated: true)
}
#endif
func changeIdentityButton(identification: Identification) -> UIButton {
let changeIdentityButton = UIButton()
let downsampled = KingfisherOptionsInfo.downsampled(

View File

@ -45,6 +45,7 @@ public final class NewStatusViewModel: ObservableObject {
public extension NewStatusViewModel {
enum Event {
case presentMediaPicker(CompositionViewModel)
case presentCamera(CompositionViewModel)
}
enum PostingState {
@ -76,6 +77,10 @@ public extension NewStatusViewModel {
eventsSubject.send(.presentMediaPicker(viewModel))
}
func presentCamera(viewModel: CompositionViewModel) {
eventsSubject.send(.presentCamera(viewModel))
}
func insert(after: CompositionViewModel) {
guard let index = compositionViewModels.firstIndex(where: { $0 === after })
else { return }

View File

@ -1,5 +1,6 @@
// Copyright © 2020 Metabolist. All rights reserved.
import AVFoundation
import Combine
import Mastodon
import UIKit
@ -59,6 +60,25 @@ private extension CompositionInputAccessoryView {
},
for: .touchUpInside)
#if !IS_SHARE_EXTENSION
if AVCaptureDevice.authorizationStatus(for: .video) != .restricted {
let cameraButton = UIButton()
stackView.addArrangedSubview(cameraButton)
cameraButton.setImage(
UIImage(
systemName: "camera",
withConfiguration: UIImage.SymbolConfiguration(scale: .medium)),
for: .normal)
cameraButton.addAction(UIAction { [weak self] _ in
guard let self = self else { return }
self.parentViewModel.presentCamera(viewModel: self.viewModel)
},
for: .touchUpInside)
}
#endif
let pollButton = UIButton()
stackView.addArrangedSubview(pollButton)