mastodon-ios/ShareActionExtension/Scene/View/ComposeView.swift

152 lines
6.0 KiB
Swift

//
// ComposeView.swift
//
//
// Created by MainasuK Cirno on 2021-7-16.
//
import UIKit
import SwiftUI
public struct ComposeView: View {
@EnvironmentObject var viewModel: ComposeViewModel
@State var statusEditorViewWidth: CGFloat = .zero
let horizontalMargin: CGFloat = 20
public init() { }
public var body: some View {
GeometryReader { proxy in
List {
// Content Warning
if viewModel.isContentWarningComposing {
ContentWarningEditorView(
contentWarningContent: $viewModel.contentWarningContent,
placeholder: viewModel.contentWarningPlaceholder
)
.padding(EdgeInsets(top: 6, leading: horizontalMargin, bottom: 6, trailing: horizontalMargin))
.background(viewModel.contentWarningBackgroundColor)
.transition(.opacity)
.listRow(backgroundColor: Color(viewModel.backgroundColor))
}
// Author
StatusAuthorView(
avatarImageURL: viewModel.avatarImageURL,
name: viewModel.authorName,
username: viewModel.authorUsername
)
.padding(EdgeInsets(top: 20, leading: horizontalMargin, bottom: 16, trailing: horizontalMargin))
.listRow(backgroundColor: Color(viewModel.backgroundColor))
// Editor
StatusEditorView(
string: $viewModel.statusContent,
placeholder: viewModel.statusPlaceholder,
width: statusEditorViewWidth,
attributedString: viewModel.statusContentAttributedString,
keyboardType: .twitter,
viewDidAppear: $viewModel.viewDidAppear
)
.frame(width: statusEditorViewWidth)
.frame(minHeight: 100)
.padding(EdgeInsets(top: 0, leading: horizontalMargin, bottom: 0, trailing: horizontalMargin))
.listRow(backgroundColor: Color(viewModel.backgroundColor))
// Attachments
ForEach(viewModel.attachmentViewModels) { attachmentViewModel in
let descriptionBinding = Binding {
return attachmentViewModel.descriptionContent
} set: { newValue in
attachmentViewModel.descriptionContent = newValue
}
StatusAttachmentView(
image: attachmentViewModel.thumbnailImage,
descriptionPlaceholder: attachmentViewModel.descriptionPlaceholder,
description: descriptionBinding,
errorPrompt: attachmentViewModel.errorPrompt,
errorPromptImage: attachmentViewModel.errorPromptImage,
isUploading: attachmentViewModel.isUploading,
progressViewTintColor: attachmentViewModel.progressViewTintColor,
removeButtonAction: {
self.viewModel.removeAttachmentViewModel(attachmentViewModel)
}
)
}
.padding(EdgeInsets(top: 16, leading: horizontalMargin, bottom: 0, trailing: horizontalMargin))
.fixedSize(horizontal: false, vertical: true)
.listRow(backgroundColor: Color(viewModel.backgroundColor))
// bottom padding
Color.clear
.frame(height: viewModel.toolbarHeight + 20)
.listRow(backgroundColor: Color(viewModel.backgroundColor))
} // end List
.listStyle(.plain)
.introspectTableView(customize: { tableView in
// tableView.keyboardDismissMode = .onDrag
tableView.verticalScrollIndicatorInsets.bottom = viewModel.toolbarHeight
})
.preference(
key: ComposeListViewFramePreferenceKey.self,
value: proxy.frame(in: .local)
)
.onPreferenceChange(ComposeListViewFramePreferenceKey.self) { frame in
var frame = frame
frame.size.width = frame.width - 2 * horizontalMargin
statusEditorViewWidth = frame.width
} // end List
.introspectTableView(customize: { tableView in
tableView.backgroundColor = .clear
})
.overrideBackground(color: Color(viewModel.backgroundColor))
} // end GeometryReader
} // end body
}
struct ComposeListViewFramePreferenceKey: PreferenceKey {
static var defaultValue: CGRect = .zero
static func reduce(value: inout CGRect, nextValue: () -> CGRect) { }
}
extension View {
// hack for separator line
@ViewBuilder
func listRow(backgroundColor: Color) -> some View {
// expand list row to edge (set inset)
// then hide the separator
if #available(iOS 15, *) {
frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.listRowInsets(EdgeInsets(top: -1, leading: -1, bottom: -1, trailing: -1))
.background(backgroundColor)
.listRowSeparator(.hidden) // new API
} else {
frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .leading)
.listRowInsets(EdgeInsets(top: -1, leading: -1, bottom: -1, trailing: -1)) // separator line hidden magic
.background(backgroundColor)
}
}
@ViewBuilder
func overrideBackground(color: Color) -> some View {
background(color.ignoresSafeArea())
}
}
struct ComposeView_Previews: PreviewProvider {
static let viewModel: ComposeViewModel = {
let viewModel = ComposeViewModel()
return viewModel
}()
static var previews: some View {
ComposeView().environmentObject(viewModel)
}
}