Camera
This commit is contained in:
parent
3b0f0bf82f
commit
5ae1d9be9a
|
@ -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";
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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(
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue