73 lines
1.8 KiB
Swift

//
// ComposeInput.swift
// ComposeUI
//
// Created by Shadowfacts on 3/5/23.
//
import Foundation
import Combine
import UIKit
import SwiftUI
protocol ComposeInput: AnyObject, ObservableObject {
var toolbarElements: [ToolbarElement] { get }
var textInputMode: UITextInputMode? { get }
var autocompleteState: AutocompleteState? { get }
var autocompleteStatePublisher: Published<AutocompleteState?>.Publisher { get }
func autocomplete(with string: String)
func applyFormat(_ format: StatusFormat)
func beginAutocompletingEmoji()
}
enum ToolbarElement {
case emojiPicker
case formattingButtons
}
private struct FocusedComposeInput: FocusedValueKey {
typealias Value = (any ComposeInput)?
}
extension FocusedValues {
// double optional is necessary pre-iOS 16
var composeInput: (any ComposeInput)?? {
get { self[FocusedComposeInput.self] }
set { self[FocusedComposeInput.self] = newValue }
}
}
@propertyWrapper
final class MutableObservableBox<Value>: ObservableObject {
@Published var wrappedValue: Value
init(wrappedValue: Value) {
self.wrappedValue = wrappedValue
}
}
private struct FocusedComposeInputBox: EnvironmentKey {
static let defaultValue: MutableObservableBox<(any ComposeInput)?> = .init(wrappedValue: nil)
}
extension EnvironmentValues {
var composeInputBox: MutableObservableBox<(any ComposeInput)?> {
get { self[FocusedComposeInputBox.self] }
set { self[FocusedComposeInputBox.self] = newValue }
}
}
struct FocusedInputModifier: ViewModifier {
@StateObject var box: MutableObservableBox<(any ComposeInput)?> = .init(wrappedValue: nil)
func body(content: Content) -> some View {
content
.environment(\.composeInputBox, box)
.focusedValue(\.composeInput, box.wrappedValue)
}
}