Make things compile on iOS 15
This commit is contained in:
parent
c68902b34b
commit
6730575aed
@ -30,11 +30,12 @@ enum ToolbarElement {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private struct FocusedComposeInput: FocusedValueKey {
|
private struct FocusedComposeInput: FocusedValueKey {
|
||||||
typealias Value = any ComposeInput
|
typealias Value = (any ComposeInput)?
|
||||||
}
|
}
|
||||||
|
|
||||||
extension FocusedValues {
|
extension FocusedValues {
|
||||||
var composeInput: (any ComposeInput)? {
|
// double optional is necessary pre-iOS 16
|
||||||
|
var composeInput: (any ComposeInput)?? {
|
||||||
get { self[FocusedComposeInput.self] }
|
get { self[FocusedComposeInput.self] }
|
||||||
set { self[FocusedComposeInput.self] = newValue }
|
set { self[FocusedComposeInput.self] = newValue }
|
||||||
}
|
}
|
||||||
|
@ -221,16 +221,3 @@ extension AttachmentRowController {
|
|||||||
case allowEntry, recognizingText
|
case allowEntry, recognizingText
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension View {
|
|
||||||
@available(iOS, obsoleted: 16.0)
|
|
||||||
@available(visionOS 1.0, *)
|
|
||||||
@ViewBuilder
|
|
||||||
func contextMenu<M: View, P: View>(@ViewBuilder menuItems: () -> M, @ViewBuilder previewIfAvailable preview: () -> P) -> some View {
|
|
||||||
if #available(iOS 16.0, *) {
|
|
||||||
self.contextMenu(menuItems: menuItems, preview: preview)
|
|
||||||
} else {
|
|
||||||
self.contextMenu(menuItems: menuItems)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -509,18 +509,6 @@ public final class ComposeController: ViewController {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension View {
|
|
||||||
@available(iOS, obsoleted: 16.0)
|
|
||||||
@ViewBuilder
|
|
||||||
func scrollDismissesKeyboardInteractivelyIfAvailable() -> some View {
|
|
||||||
if #available(iOS 16.0, *) {
|
|
||||||
self.scrollDismissesKeyboard(.interactively)
|
|
||||||
} else {
|
|
||||||
self
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private struct GlobalFrameOutsideListPrefKey: PreferenceKey {
|
private struct GlobalFrameOutsideListPrefKey: PreferenceKey {
|
||||||
static var defaultValue: CGRect = .zero
|
static var defaultValue: CGRect = .zero
|
||||||
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
|
static func reduce(value: inout CGRect, nextValue: () -> CGRect) {
|
||||||
|
@ -23,4 +23,33 @@ extension View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@available(iOS, obsoleted: 16.0)
|
||||||
|
@ViewBuilder
|
||||||
|
func scrollDismissesKeyboardInteractivelyIfAvailable() -> some View {
|
||||||
|
#if os(visionOS)
|
||||||
|
self.scrollDismissesKeyboard(.interactively)
|
||||||
|
#else
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
self.scrollDismissesKeyboard(.interactively)
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
@available(iOS, obsoleted: 16.0)
|
||||||
|
@available(visionOS 1.0, *)
|
||||||
|
@ViewBuilder
|
||||||
|
func contextMenu<M: View, P: View>(@ViewBuilder menuItems: () -> M, @ViewBuilder previewIfAvailable preview: () -> P) -> some View {
|
||||||
|
#if os(visionOS)
|
||||||
|
self.contextMenu(menuItems: menuItems, preview: preview)
|
||||||
|
#else
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
self.contextMenu(menuItems: menuItems, preview: preview)
|
||||||
|
} else {
|
||||||
|
self.contextMenu(menuItems: menuItems)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ struct AttachmentRowView: View {
|
|||||||
EditDrawingButton(attachment: attachment)
|
EditDrawingButton(attachment: attachment)
|
||||||
RecognizeTextButton(attachment: attachment, isRecognizingText: $isRecognizingText, error: $textRecognitionError)
|
RecognizeTextButton(attachment: attachment, isRecognizingText: $isRecognizingText, error: $textRecognitionError)
|
||||||
DeleteButton(attachment: attachment)
|
DeleteButton(attachment: attachment)
|
||||||
} preview: {
|
} previewIfAvailable: {
|
||||||
// TODO: need to fix flash of preview changing size
|
// TODO: need to fix flash of preview changing size
|
||||||
AttachmentThumbnailView(attachment: attachment)
|
AttachmentThumbnailView(attachment: attachment)
|
||||||
}
|
}
|
||||||
|
@ -114,9 +114,21 @@ private struct AttachmentThumbnailViewContent: View {
|
|||||||
let asset = AVURLAsset(url: url)
|
let asset = AVURLAsset(url: url)
|
||||||
let imageGenerator = AVAssetImageGenerator(asset: asset)
|
let imageGenerator = AVAssetImageGenerator(asset: asset)
|
||||||
imageGenerator.appliesPreferredTrackTransform = true
|
imageGenerator.appliesPreferredTrackTransform = true
|
||||||
|
#if os(visionOS)
|
||||||
if let (cgImage, _) = try? await imageGenerator.image(at: .zero) {
|
if let (cgImage, _) = try? await imageGenerator.image(at: .zero) {
|
||||||
self.mode = .image(UIImage(cgImage: cgImage))
|
self.mode = .image(UIImage(cgImage: cgImage))
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
if let (cgImage, _) = try? await imageGenerator.image(at: .zero) {
|
||||||
|
self.mode = .image(UIImage(cgImage: cgImage))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if let cgImage = try? imageGenerator.copyCGImage(at: .zero, actualTime: nil) {
|
||||||
|
self.mode = .image(UIImage(cgImage: cgImage))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
enum Mode {
|
enum Mode {
|
||||||
|
@ -9,12 +9,14 @@ import UIKit
|
|||||||
import SwiftUI
|
import SwiftUI
|
||||||
|
|
||||||
final class AttachmentCollectionViewCell: UICollectionViewCell {
|
final class AttachmentCollectionViewCell: UICollectionViewCell {
|
||||||
let attachmentView: UIView & UIContentView
|
let attachmentView: UIView// & UIContentView
|
||||||
|
|
||||||
override init(frame: CGRect) {
|
override init(frame: CGRect) {
|
||||||
attachmentView = UIHostingConfiguration(content: {
|
attachmentView = UIView()
|
||||||
AttachmentCollectionViewCellView(attachment: nil)
|
attachmentView.backgroundColor = .red
|
||||||
}).makeContentView()
|
// attachmentView = UIHostingConfiguration(content: {
|
||||||
|
// AttachmentCollectionViewCellView(attachment: nil)
|
||||||
|
// }).makeContentView()
|
||||||
|
|
||||||
super.init(frame: frame)
|
super.init(frame: frame)
|
||||||
|
|
||||||
@ -27,9 +29,9 @@ final class AttachmentCollectionViewCell: UICollectionViewCell {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func updateUI(attachment: DraftAttachment) {
|
func updateUI(attachment: DraftAttachment) {
|
||||||
attachmentView.configuration = UIHostingConfiguration(content: {
|
// attachmentView.configuration = UIHostingConfiguration(content: {
|
||||||
AttachmentCollectionViewCellView(attachment: attachment)
|
// AttachmentCollectionViewCellView(attachment: attachment)
|
||||||
}).margins(.all, .zero)
|
// }).margins(.all, .zero)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -127,6 +129,7 @@ private struct RoundedSquare: Shape {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 16.0, *)
|
||||||
private struct SquareFrame: Layout {
|
private struct SquareFrame: Layout {
|
||||||
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
||||||
precondition(subviews.count == 1)
|
precondition(subviews.count == 1)
|
||||||
@ -145,10 +148,21 @@ private struct SquareFrame: Layout {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private extension View {
|
private extension View {
|
||||||
|
@ViewBuilder
|
||||||
func squareFrame() -> some View {
|
func squareFrame() -> some View {
|
||||||
|
#if os(visionOS)
|
||||||
SquareFrame {
|
SquareFrame {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
SquareFrame {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,8 +70,8 @@ private class WrappedCollectionViewController: UIViewController {
|
|||||||
let layout = UICollectionViewCompositionalLayout { [unowned self] section, environment in
|
let layout = UICollectionViewCompositionalLayout { [unowned self] section, environment in
|
||||||
let (itemSize, itemsPerRow) = self.itemSize(width: environment.container.contentSize.width)
|
let (itemSize, itemsPerRow) = self.itemSize(width: environment.container.contentSize.width)
|
||||||
|
|
||||||
let item = NSCollectionLayoutItem(layoutSize: .init(widthDimension: .absolute(itemSize), heightDimension: .absolute(itemSize)))
|
let items = Array(repeating: NSCollectionLayoutItem(layoutSize: .init(widthDimension: .absolute(itemSize), heightDimension: .absolute(itemSize))), count: itemsPerRow)
|
||||||
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(itemSize)), repeatingSubitem: item, count: itemsPerRow)
|
let group = NSCollectionLayoutGroup.horizontal(layoutSize: .init(widthDimension: .fractionalWidth(1), heightDimension: .absolute(itemSize)), subitems: items)
|
||||||
group.interItemSpacing = .fixed(spacing)
|
group.interItemSpacing = .fixed(spacing)
|
||||||
let section = NSCollectionLayoutSection(group: group)
|
let section = NSCollectionLayoutSection(group: group)
|
||||||
section.interGroupSpacing = spacing
|
section.interGroupSpacing = spacing
|
||||||
@ -81,9 +81,10 @@ private class WrappedCollectionViewController: UIViewController {
|
|||||||
cell.updateUI(attachment: attachment)
|
cell.updateUI(attachment: attachment)
|
||||||
}
|
}
|
||||||
let addButtonCell = UICollectionView.CellRegistration<UICollectionViewCell, Bool> { [unowned self] cell, indexPath, item in
|
let addButtonCell = UICollectionView.CellRegistration<UICollectionViewCell, Bool> { [unowned self] cell, indexPath, item in
|
||||||
cell.contentConfiguration = UIHostingConfiguration(content: {
|
cell.contentView.backgroundColor = .blue
|
||||||
AddAttachmentButton(viewController: self, enabled: item)
|
// cell.contentConfiguration = UIHostingConfiguration(content: {
|
||||||
}).margins(.all, .zero)
|
// AddAttachmentButton(viewController: self, enabled: item)
|
||||||
|
// }).margins(.all, .zero)
|
||||||
}
|
}
|
||||||
let collectionView = IntrinsicContentSizeCollectionView(frame: .zero, collectionViewLayout: layout)
|
let collectionView = IntrinsicContentSizeCollectionView(frame: .zero, collectionViewLayout: layout)
|
||||||
self.view = collectionView
|
self.view = collectionView
|
||||||
|
@ -72,7 +72,7 @@ private struct ToolbarScrollView<Content: View>: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.scrollDisabled(realWidth ?? 0 <= minWidth ?? 0)
|
.scrollDisabledIfAvailable(realWidth ?? 0 <= minWidth ?? 0)
|
||||||
.frame(maxWidth: .infinity)
|
.frame(maxWidth: .infinity)
|
||||||
.background {
|
.background {
|
||||||
GeometryReader { proxy in
|
GeometryReader { proxy in
|
||||||
@ -182,7 +182,7 @@ private struct InsertEmojiButton: View {
|
|||||||
@ScaledMetric(relativeTo: .body) private var imageSize: CGFloat = 22
|
@ScaledMetric(relativeTo: .body) private var imageSize: CGFloat = 22
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if input?.toolbarElements.contains(.emojiPicker) == true {
|
if input??.toolbarElements.contains(.emojiPicker) == true {
|
||||||
Button(action: beginAutocompletingEmoji) {
|
Button(action: beginAutocompletingEmoji) {
|
||||||
Label("Insert custom emoji", systemImage: "face.smiling")
|
Label("Insert custom emoji", systemImage: "face.smiling")
|
||||||
}
|
}
|
||||||
@ -195,7 +195,7 @@ private struct InsertEmojiButton: View {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private func beginAutocompletingEmoji() {
|
private func beginAutocompletingEmoji() {
|
||||||
input?.beginAutocompletingEmoji()
|
input??.beginAutocompletingEmoji()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -204,7 +204,7 @@ private struct FormatButtons: View {
|
|||||||
@PreferenceObserving(\.$statusContentType) private var contentType
|
@PreferenceObserving(\.$statusContentType) private var contentType
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if let input,
|
if let input = input.flatMap(\.self),
|
||||||
input.toolbarElements.contains(.formattingButtons),
|
input.toolbarElements.contains(.formattingButtons),
|
||||||
contentType != .plain {
|
contentType != .plain {
|
||||||
|
|
||||||
|
@ -15,10 +15,28 @@ struct ComposeView: View {
|
|||||||
@EnvironmentObject private var controller: ComposeController
|
@EnvironmentObject private var controller: ComposeController
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
|
navigation
|
||||||
|
.environmentObject(mastodonController.instanceFeatures)
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private var navigation: some View {
|
||||||
|
#if os(visionOS)
|
||||||
NavigationStack {
|
NavigationStack {
|
||||||
navigationRoot
|
navigationRoot
|
||||||
}
|
}
|
||||||
.environmentObject(mastodonController.instanceFeatures)
|
#else
|
||||||
|
if #available(iOS 16.0, *) {
|
||||||
|
NavigationStack {
|
||||||
|
navigationRoot
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
NavigationView {
|
||||||
|
navigationRoot
|
||||||
|
}
|
||||||
|
.navigationViewStyle(.stack)
|
||||||
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private var navigationRoot: some View {
|
private var navigationRoot: some View {
|
||||||
@ -26,7 +44,7 @@ struct ComposeView: View {
|
|||||||
ScrollView {
|
ScrollView {
|
||||||
scrollContent
|
scrollContent
|
||||||
}
|
}
|
||||||
.scrollDismissesKeyboard(.interactively)
|
.scrollDismissesKeyboardInteractivelyIfAvailable()
|
||||||
#if !os(visionOS) && !targetEnvironment(macCatalyst)
|
#if !os(visionOS) && !targetEnvironment(macCatalyst)
|
||||||
.modifier(ToolbarSafeAreaInsetModifier())
|
.modifier(ToolbarSafeAreaInsetModifier())
|
||||||
#endif
|
#endif
|
||||||
|
@ -62,7 +62,8 @@ private struct LanguageButton: View {
|
|||||||
@State private var hasChanged = false
|
@State private var hasChanged = false
|
||||||
|
|
||||||
var body: some View {
|
var body: some View {
|
||||||
if instanceFeatures.createStatusWithLanguage {
|
if #available(iOS 16.0, *),
|
||||||
|
instanceFeatures.createStatusWithLanguage {
|
||||||
LanguagePicker(draftLanguage: $draft.language, hasChangedSelection: $hasChanged)
|
LanguagePicker(draftLanguage: $draft.language, hasChangedSelection: $hasChanged)
|
||||||
.buttonStyle(LanguageButtonStyle())
|
.buttonStyle(LanguageButtonStyle())
|
||||||
.onReceive(NotificationCenter.default.publisher(for: UITextInputMode.currentInputModeDidChangeNotification), perform: currentInputModeChanged)
|
.onReceive(NotificationCenter.default.publisher(for: UITextInputMode.currentInputModeDidChangeNotification), perform: currentInputModeChanged)
|
||||||
@ -72,10 +73,11 @@ private struct LanguageButton: View {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@available(iOS 16.0, *)
|
||||||
private func currentInputModeChanged(_ notification: Foundation.Notification) {
|
private func currentInputModeChanged(_ notification: Foundation.Notification) {
|
||||||
guard !hasChanged,
|
guard !hasChanged,
|
||||||
!draft.hasContent,
|
!draft.hasContent,
|
||||||
let mode = input?.textInputMode,
|
let mode = input??.textInputMode,
|
||||||
let code = LanguagePicker.codeFromInputMode(mode) else {
|
let code = LanguagePicker.codeFromInputMode(mode) else {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,11 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
|||||||
|
|
||||||
func makeUIView(context: Context) -> UITextView {
|
func makeUIView(context: Context) -> UITextView {
|
||||||
// TODO: if we're not doing the pill background, reevaluate whether this version fork is necessary
|
// TODO: if we're not doing the pill background, reevaluate whether this version fork is necessary
|
||||||
let view = WrappedTextView(usingTextLayoutManager: true)
|
let view = if #available(iOS 16.0, *) {
|
||||||
|
WrappedTextView(usingTextLayoutManager: true)
|
||||||
|
} else {
|
||||||
|
WrappedTextView()
|
||||||
|
}
|
||||||
view.addInteraction(UIDropInteraction(delegate: context.coordinator))
|
view.addInteraction(UIDropInteraction(delegate: context.coordinator))
|
||||||
view.delegate = context.coordinator
|
view.delegate = context.coordinator
|
||||||
view.adjustsFontForContentSizeCategory = true
|
view.adjustsFontForContentSizeCategory = true
|
||||||
|
Loading…
x
Reference in New Issue
Block a user