Use new compose UI for share extension
This commit is contained in:
parent
c7c363782b
commit
e9e08bdadd
@ -24,9 +24,10 @@ public struct ComposeUIConfig {
|
||||
public var groupedBackgroundColor = Color(uiColor: .systemGroupedBackground)
|
||||
public var groupedCellBackgroundColor = Color(uiColor: .systemBackground)
|
||||
public var fillColor = Color(uiColor: .systemFill)
|
||||
public var avatarStyle = AvatarImageView.Style.roundRect
|
||||
|
||||
// TODO: remove these in favor of @PreferenceObserving
|
||||
// Preferences
|
||||
public var avatarStyle = AvatarImageView.Style.roundRect
|
||||
public var useTwitterKeyboard = false
|
||||
public var contentType = StatusContentType.plain
|
||||
public var requireAttachmentDescriptions = false
|
||||
|
@ -36,7 +36,6 @@ private struct NewMainTextViewRepresentable: UIViewRepresentable {
|
||||
@Environment(\.colorScheme) private var colorScheme
|
||||
@Environment(\.composeUIConfig.fillColor) private var fillColor
|
||||
@Environment(\.composeUIConfig.useTwitterKeyboard) private var useTwitterKeyboard
|
||||
// TODO: test textSelectionStartsAtBeginning
|
||||
@Environment(\.composeUIConfig.textSelectionStartsAtBeginning) private var textSelectionStartsAtBeginning
|
||||
|
||||
func makeUIView(context: Context) -> UITextView {
|
||||
|
@ -12,6 +12,7 @@ import TuskerComponents
|
||||
import WebURLFoundationExtras
|
||||
import Combine
|
||||
import TuskerPreferences
|
||||
import Pachyderm
|
||||
|
||||
class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
private static func fetchAvatar(_ url: URL) async -> UIImage? {
|
||||
@ -27,48 +28,21 @@ class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
return await image.byPreparingThumbnail(ofSize: CGSize(width: size, height: size)) ?? image
|
||||
}
|
||||
|
||||
private let controller: ComposeController
|
||||
|
||||
private var mastodonContextPublisher: CurrentValueSubject<ShareMastodonContext, Never>
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
@ObservableObjectBox private var config = ComposeUIConfig()
|
||||
private let accountSwitchingState: AccountSwitchingState
|
||||
private let state: ComposeViewState
|
||||
|
||||
init(draft: Draft, mastodonContext: ShareMastodonContext) {
|
||||
let mastodonContextPublisher = CurrentValueSubject<ShareMastodonContext, Never>(mastodonContext)
|
||||
self.mastodonContextPublisher = mastodonContextPublisher
|
||||
controller = ComposeController(
|
||||
draft: draft,
|
||||
config: ComposeUIConfig(),
|
||||
mastodonController: mastodonContext,
|
||||
fetchAvatar: Self.fetchAvatar,
|
||||
fetchAttachment: { _ in fatalError("edits aren't allowed in share sheet, can't fetch existing attachment") },
|
||||
fetchStatus: { _ in fatalError("replies aren't allowed in share sheet") },
|
||||
displayNameLabel: { account, style, _ in AnyView(Text(account.displayName).font(.system(style))) },
|
||||
currentAccountContainerView: { AnyView(SwitchAccountContainerView(content: $0, mastodonContextPublisher: mastodonContextPublisher)) },
|
||||
replyContentView: { _, _ in fatalError("replies aren't allowed in share sheet") },
|
||||
emojiImageView: {
|
||||
AnyView(AsyncImage(url: URL($0.url)!) {
|
||||
$0
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
} placeholder: {
|
||||
Image(systemName: "smiley.fill")
|
||||
})
|
||||
}
|
||||
self.accountSwitchingState = AccountSwitchingState(mastodonContext: mastodonContext)
|
||||
self.state = ComposeViewState(draft: draft)
|
||||
let rootView = View(
|
||||
accountSwitchingState: self.accountSwitchingState,
|
||||
state: state,
|
||||
config: _config
|
||||
)
|
||||
super.init(rootView: View(controller: controller))
|
||||
super.init(rootView: rootView)
|
||||
|
||||
updateConfig()
|
||||
|
||||
mastodonContextPublisher
|
||||
.sink { [unowned self] in
|
||||
self.controller.mastodonController = $0
|
||||
self.controller.draft.accountID = $0.accountInfo!.id
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
mastodonContextPublisher
|
||||
.flatMap { $0.$ownAccount }
|
||||
.sink { [unowned self] in self.controller.currentAccount = $0 }
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
required init?(coder aDecoder: NSCoder) {
|
||||
@ -95,8 +69,13 @@ class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
config.requireAttachmentDescriptions = Preferences.shared.requireAttachmentDescriptions
|
||||
|
||||
config.dismiss = { [unowned self] in self.dismiss(mode: $0) }
|
||||
config.fetchAvatar = Self.fetchAvatar
|
||||
config.displayNameLabel = { account, style, _ in
|
||||
// TODO: move AccountDisplayNameView to TuskerComponents and use that here as well
|
||||
AnyView(Text(account.displayName).font(.system(style)))
|
||||
}
|
||||
|
||||
controller.config = config
|
||||
self.config = config
|
||||
}
|
||||
|
||||
private func dismiss(mode: DismissMode) {
|
||||
@ -110,10 +89,35 @@ class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
}
|
||||
|
||||
struct View: SwiftUI.View {
|
||||
let controller: ComposeController
|
||||
@ObservedObject var accountSwitchingState: AccountSwitchingState
|
||||
let state: ComposeViewState
|
||||
@ObservedObject @ObservableObjectBox private var config: ComposeUIConfig
|
||||
@State private var currentAccount: Account?
|
||||
|
||||
fileprivate init(
|
||||
accountSwitchingState: AccountSwitchingState,
|
||||
state: ComposeViewState,
|
||||
config: ObservableObjectBox<ComposeUIConfig>
|
||||
) {
|
||||
self.accountSwitchingState = accountSwitchingState
|
||||
self.state = state
|
||||
self._config = ObservedObject(wrappedValue: config)
|
||||
self._currentAccount = State(wrappedValue: accountSwitchingState.currentAccount)
|
||||
}
|
||||
|
||||
var body: some SwiftUI.View {
|
||||
ControllerView(controller: { controller })
|
||||
ComposeView(
|
||||
state: state,
|
||||
mastodonController: accountSwitchingState.mastodonContext,
|
||||
currentAccount: currentAccount,
|
||||
config: config
|
||||
)
|
||||
.onReceive(accountSwitchingState.$mastodonContext) {
|
||||
state.draft.accountID = $0.accountInfo!.id
|
||||
}
|
||||
.onReceive(accountSwitchingState.currentAccountPublisher) {
|
||||
currentAccount = $0
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -122,6 +126,16 @@ class ShareHostingController: UIHostingController<ShareHostingController.View> {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: put this somewhere instead of just copying it from ComposeHostingController
|
||||
@MainActor
|
||||
@propertyWrapper
|
||||
private final class ObservableObjectBox<T>: ObservableObject {
|
||||
@Published var wrappedValue: T
|
||||
init(wrappedValue: T) {
|
||||
self.wrappedValue = wrappedValue
|
||||
}
|
||||
}
|
||||
|
||||
// todo: shouldn't just copy this from the main Colors.swift
|
||||
extension UIColor {
|
||||
static let appBackground = UIColor { traitCollection in
|
||||
|
@ -13,9 +13,28 @@ import Pachyderm
|
||||
import Combine
|
||||
import ComposeUI
|
||||
|
||||
@MainActor
|
||||
class AccountSwitchingState: ObservableObject {
|
||||
@Published var mastodonContext: ShareMastodonContext
|
||||
|
||||
var currentAccount: Account? {
|
||||
mastodonContext.ownAccount
|
||||
}
|
||||
|
||||
var currentAccountPublisher: some Publisher<Account, Never> {
|
||||
$mastodonContext
|
||||
.flatMap { $0.$ownAccount }
|
||||
.compactMap { $0 }
|
||||
}
|
||||
|
||||
init(mastodonContext: ShareMastodonContext) {
|
||||
self.mastodonContext = mastodonContext
|
||||
}
|
||||
}
|
||||
|
||||
struct SwitchAccountContainerView: View {
|
||||
let content: AnyView
|
||||
let mastodonContextPublisher: CurrentValueSubject<ShareMastodonContext, Never>
|
||||
@ObservedObject var state: AccountSwitchingState
|
||||
|
||||
var accounts: [UserAccountInfo] {
|
||||
UserAccountsManager.shared.accounts
|
||||
@ -50,7 +69,7 @@ struct SwitchAccountContainerView: View {
|
||||
}
|
||||
|
||||
private func selectAccount(_ account: UserAccountInfo) {
|
||||
mastodonContextPublisher.send(ShareMastodonContext(accountInfo: account))
|
||||
state.mastodonContext = ShareMastodonContext(accountInfo: account)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -45,8 +45,7 @@ class ComposeHostingController: UIHostingController<ComposeHostingController.Vie
|
||||
self.mastodonController = mastodonController
|
||||
self.config = ComposeUIConfig()
|
||||
self.currentAccount = mastodonController.account
|
||||
let state = ComposeViewState(draft: draft)
|
||||
self.state = state
|
||||
self.state = ComposeViewState(draft: draft)
|
||||
|
||||
let rootView = View(
|
||||
state: state,
|
||||
|
Loading…
x
Reference in New Issue
Block a user