feat: add toolbar for compose scene
This commit is contained in:
parent
d9e2453464
commit
1746c1fc77
|
@ -203,6 +203,7 @@
|
||||||
DB9D6C2E25E504AC0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C2D25E504AC0051B173 /* Attachment.swift */; };
|
DB9D6C2E25E504AC0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C2D25E504AC0051B173 /* Attachment.swift */; };
|
||||||
DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C3725E508BE0051B173 /* Attachment.swift */; };
|
DB9D6C3825E508BE0051B173 /* Attachment.swift in Sources */ = {isa = PBXBuildFile; fileRef = DB9D6C3725E508BE0051B173 /* Attachment.swift */; };
|
||||||
DBA0A10925FB3C2B0079C110 /* RoundedEdgesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */; };
|
DBA0A10925FB3C2B0079C110 /* RoundedEdgesButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */; };
|
||||||
|
DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBA0A11225FB3FC10079C110 /* ComposeToolbarView.swift */; };
|
||||||
DBBE1B4525F3474B0081417A /* MastodonPickServerAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */; };
|
DBBE1B4525F3474B0081417A /* MastodonPickServerAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */; };
|
||||||
DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */; };
|
DBD9149025DF6D8D00903DFD /* APIService+Onboarding.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */; };
|
||||||
DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */; };
|
DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */; };
|
||||||
|
@ -466,6 +467,7 @@
|
||||||
DB9D6C2D25E504AC0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
DB9D6C2D25E504AC0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
||||||
DB9D6C3725E508BE0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
DB9D6C3725E508BE0051B173 /* Attachment.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Attachment.swift; sourceTree = "<group>"; };
|
||||||
DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedEdgesButton.swift; sourceTree = "<group>"; };
|
DBA0A10825FB3C2B0079C110 /* RoundedEdgesButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RoundedEdgesButton.swift; sourceTree = "<group>"; };
|
||||||
|
DBA0A11225FB3FC10079C110 /* ComposeToolbarView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeToolbarView.swift; sourceTree = "<group>"; };
|
||||||
DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPickServerAppearance.swift; sourceTree = "<group>"; };
|
DBBE1B4425F3474B0081417A /* MastodonPickServerAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonPickServerAppearance.swift; sourceTree = "<group>"; };
|
||||||
DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; };
|
DBD9148F25DF6D8D00903DFD /* APIService+Onboarding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "APIService+Onboarding.swift"; sourceTree = "<group>"; };
|
||||||
DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; };
|
DBE0821425CD382600FD6BBD /* MastodonRegisterViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MastodonRegisterViewController.swift; sourceTree = "<group>"; };
|
||||||
|
@ -984,6 +986,14 @@
|
||||||
path = Preference;
|
path = Preference;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
};
|
};
|
||||||
|
DB55D32225FB4D320002F825 /* View */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
DBA0A11225FB3FC10079C110 /* ComposeToolbarView.swift */,
|
||||||
|
);
|
||||||
|
path = View;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
DB68A03825E900CC00CFDF14 /* Share */ = {
|
DB68A03825E900CC00CFDF14 /* Share */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
@ -1022,6 +1032,7 @@
|
||||||
DB789A1025F9F29B0071ACA0 /* Compose */ = {
|
DB789A1025F9F29B0071ACA0 /* Compose */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
DB55D32225FB4D320002F825 /* View */,
|
||||||
DB789A2125F9F76D0071ACA0 /* TableViewCell */,
|
DB789A2125F9F76D0071ACA0 /* TableViewCell */,
|
||||||
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */,
|
DB789A0A25F9F2950071ACA0 /* ComposeViewController.swift */,
|
||||||
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */,
|
DB789A1125F9F2CC0071ACA0 /* ComposeViewModel.swift */,
|
||||||
|
@ -1731,6 +1742,7 @@
|
||||||
DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */,
|
DBE0821525CD382600FD6BBD /* MastodonRegisterViewController.swift in Sources */,
|
||||||
2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */,
|
2D5A3D0325CF8742002347D6 /* ControlContainableScrollViews.swift in Sources */,
|
||||||
DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */,
|
DB98336B25C9420100AD9700 /* APIService+App.swift in Sources */,
|
||||||
|
DBA0A11325FB3FC10079C110 /* ComposeToolbarView.swift in Sources */,
|
||||||
2D32EADA25CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift in Sources */,
|
2D32EADA25CBCC3300C9ED86 /* PublicTimelineViewModel+LoadMiddleState.swift in Sources */,
|
||||||
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */,
|
DB8AF54425C13647002E6C99 /* SceneCoordinator.swift in Sources */,
|
||||||
5DF1058525F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift in Sources */,
|
5DF1058525F88AE500D6C0D4 /* NeedsDependency+AVPlayerViewControllerDelegate.swift in Sources */,
|
||||||
|
|
|
@ -9,6 +9,7 @@ import os.log
|
||||||
import UIKit
|
import UIKit
|
||||||
import Combine
|
import Combine
|
||||||
import TwitterTextEditor
|
import TwitterTextEditor
|
||||||
|
import KeyboardGuide
|
||||||
|
|
||||||
final class ComposeViewController: UIViewController, NeedsDependency {
|
final class ComposeViewController: UIViewController, NeedsDependency {
|
||||||
|
|
||||||
|
@ -41,6 +42,16 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
||||||
return tableView
|
return tableView
|
||||||
}()
|
}()
|
||||||
|
|
||||||
|
let composeToolbarView: ComposeToolbarView = {
|
||||||
|
let composeToolbarView = ComposeToolbarView()
|
||||||
|
return composeToolbarView
|
||||||
|
}()
|
||||||
|
var composeToolbarViewBottomLayoutConstraint: NSLayoutConstraint!
|
||||||
|
let composeToolbarBackgroundView: UIView = {
|
||||||
|
let backgroundView = UIView()
|
||||||
|
return backgroundView
|
||||||
|
}()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
extension ComposeViewController {
|
extension ComposeViewController {
|
||||||
|
@ -69,6 +80,60 @@ extension ComposeViewController {
|
||||||
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
|
||||||
])
|
])
|
||||||
|
|
||||||
|
composeToolbarView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
view.addSubview(composeToolbarView)
|
||||||
|
composeToolbarViewBottomLayoutConstraint = view.bottomAnchor.constraint(equalTo: composeToolbarView.bottomAnchor)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
composeToolbarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
|
||||||
|
composeToolbarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
|
||||||
|
composeToolbarViewBottomLayoutConstraint,
|
||||||
|
composeToolbarView.heightAnchor.constraint(equalToConstant: 44),
|
||||||
|
])
|
||||||
|
composeToolbarView.preservesSuperviewLayoutMargins = true
|
||||||
|
composeToolbarView.delegate = self
|
||||||
|
|
||||||
|
// respond scrollView overlap change
|
||||||
|
view.layoutIfNeeded()
|
||||||
|
Publishers.CombineLatest3(
|
||||||
|
KeyboardResponderService.shared.isShow.eraseToAnyPublisher(),
|
||||||
|
KeyboardResponderService.shared.state.eraseToAnyPublisher(),
|
||||||
|
KeyboardResponderService.shared.endFrame.eraseToAnyPublisher()
|
||||||
|
)
|
||||||
|
.sink(receiveValue: { [weak self] isShow, state, endFrame in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
guard isShow, state == .dock else {
|
||||||
|
self.tableView.contentInset.bottom = 0.0
|
||||||
|
self.tableView.verticalScrollIndicatorInsets.bottom = 0.0
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
self.composeToolbarViewBottomLayoutConstraint.constant = 0.0
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// isShow AND dock state
|
||||||
|
let contentFrame = self.view.convert(self.tableView.frame, to: nil)
|
||||||
|
let padding = contentFrame.maxY - endFrame.minY
|
||||||
|
guard padding > 0 else {
|
||||||
|
self.tableView.contentInset.bottom = 0.0
|
||||||
|
self.tableView.verticalScrollIndicatorInsets.bottom = 0.0
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
self.composeToolbarViewBottomLayoutConstraint.constant = 0.0
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
self.tableView.contentInset.bottom = padding
|
||||||
|
self.tableView.verticalScrollIndicatorInsets.bottom = padding
|
||||||
|
UIView.animate(withDuration: 0.3) {
|
||||||
|
self.composeToolbarViewBottomLayoutConstraint.constant = padding
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.store(in: &disposeBag)
|
||||||
|
|
||||||
tableView.delegate = self
|
tableView.delegate = self
|
||||||
viewModel.setupDiffableDataSource(for: tableView, dependency: self)
|
viewModel.setupDiffableDataSource(for: tableView, dependency: self)
|
||||||
}
|
}
|
||||||
|
@ -123,6 +188,31 @@ extension ComposeViewController: TextEditorViewTextAttributesDelegate {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// MARK: - ComposeToolbarViewDelegate
|
||||||
|
extension ComposeViewController: ComposeToolbarViewDelegate {
|
||||||
|
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, gifButtonDidPressed sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, atButtonDidPressed sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, topicButtonDidPressed sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, locationButtonDidPressed sender: UIButton) {
|
||||||
|
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s", ((#file as NSString).lastPathComponent), #line, #function)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// MARK: - UITableViewDelegate
|
// MARK: - UITableViewDelegate
|
||||||
extension ComposeViewController: UITableViewDelegate {
|
extension ComposeViewController: UITableViewDelegate {
|
||||||
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
|
||||||
|
@ -132,6 +222,14 @@ extension ComposeViewController: UITableViewDelegate {
|
||||||
|
|
||||||
// MARK: - ComposeViewController
|
// MARK: - ComposeViewController
|
||||||
extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
|
extension ComposeViewController: UIAdaptivePresentationControllerDelegate {
|
||||||
|
// func adaptivePresentationStyle(for controller: UIPresentationController, traitCollection: UITraitCollection) -> UIModalPresentationStyle {
|
||||||
|
// switch traitCollection.userInterfaceIdiom {
|
||||||
|
// case .phone:
|
||||||
|
// return .fullScreen
|
||||||
|
// default:
|
||||||
|
// return .pageSheet
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
|
func presentationControllerShouldDismiss(_ presentationController: UIPresentationController) -> Bool {
|
||||||
return viewModel.shouldDismiss.value
|
return viewModel.shouldDismiss.value
|
||||||
|
|
|
@ -0,0 +1,154 @@
|
||||||
|
//
|
||||||
|
// ComposeToolbarView.swift
|
||||||
|
// Mastodon
|
||||||
|
//
|
||||||
|
// Created by MainasuK Cirno on 2021-3-12.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
|
||||||
|
protocol ComposeToolbarViewDelegate: class {
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, cameraButtonDidPressed sender: UIButton)
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, gifButtonDidPressed sender: UIButton)
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, atButtonDidPressed sender: UIButton)
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, topicButtonDidPressed sender: UIButton)
|
||||||
|
func composeToolbarView(_ composeToolbarView: ComposeToolbarView, locationButtonDidPressed sender: UIButton)
|
||||||
|
}
|
||||||
|
|
||||||
|
final class ComposeToolbarView: UIView {
|
||||||
|
|
||||||
|
weak var delegate: ComposeToolbarViewDelegate?
|
||||||
|
|
||||||
|
let mediaButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.tintColor = Asset.Colors.Button.normal.color
|
||||||
|
button.setImage(UIImage(systemName: "photo", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular)), for: .normal)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
let pollButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.tintColor = Asset.Colors.Button.normal.color
|
||||||
|
button.setImage(UIImage(systemName: "list.bullet", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .medium)), for: .normal)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
let emojiButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.tintColor = Asset.Colors.Button.normal.color
|
||||||
|
button.setImage(UIImage(systemName: "face.smiling", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular)), for: .normal)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
let contentWarningButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.tintColor = Asset.Colors.Button.normal.color
|
||||||
|
button.setImage(UIImage(systemName: "exclamationmark.shield", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular)), for: .normal)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
let visibilityButton: UIButton = {
|
||||||
|
let button = UIButton(type: .custom)
|
||||||
|
button.tintColor = Asset.Colors.Button.normal.color
|
||||||
|
button.setImage(UIImage(systemName: "person.3", withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .medium)), for: .normal)
|
||||||
|
return button
|
||||||
|
}()
|
||||||
|
|
||||||
|
override init(frame: CGRect) {
|
||||||
|
super.init(frame: frame)
|
||||||
|
_init()
|
||||||
|
}
|
||||||
|
|
||||||
|
required init?(coder: NSCoder) {
|
||||||
|
super.init(coder: coder)
|
||||||
|
_init()
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ComposeToolbarView {
|
||||||
|
private func _init() {
|
||||||
|
backgroundColor = .secondarySystemBackground
|
||||||
|
|
||||||
|
let stackView = UIStackView()
|
||||||
|
stackView.axis = .horizontal
|
||||||
|
stackView.spacing = 0
|
||||||
|
stackView.distribution = .fillEqually
|
||||||
|
stackView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
addSubview(stackView)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
stackView.centerYAnchor.constraint(equalTo: centerYAnchor),
|
||||||
|
layoutMarginsGuide.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: 8), // tweak button margin offset
|
||||||
|
])
|
||||||
|
|
||||||
|
let buttons = [
|
||||||
|
mediaButton,
|
||||||
|
pollButton,
|
||||||
|
emojiButton,
|
||||||
|
contentWarningButton,
|
||||||
|
visibilityButton,
|
||||||
|
]
|
||||||
|
buttons.forEach { button in
|
||||||
|
button.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
stackView.addArrangedSubview(button)
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
button.widthAnchor.constraint(equalToConstant: 44),
|
||||||
|
button.heightAnchor.constraint(equalToConstant: 44),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
||||||
|
mediaButton.addTarget(self, action: #selector(ComposeToolbarView.cameraButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
|
pollButton.addTarget(self, action: #selector(ComposeToolbarView.gifButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
|
emojiButton.addTarget(self, action: #selector(ComposeToolbarView.atButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
|
contentWarningButton.addTarget(self, action: #selector(ComposeToolbarView.topicButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
|
visibilityButton.addTarget(self, action: #selector(ComposeToolbarView.locationButtonDidPressed(_:)), for: .touchUpInside)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
extension ComposeToolbarView {
|
||||||
|
|
||||||
|
@objc private func cameraButtonDidPressed(_ sender: UIButton) {
|
||||||
|
delegate?.composeToolbarView(self, cameraButtonDidPressed: sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func gifButtonDidPressed(_ sender: UIButton) {
|
||||||
|
delegate?.composeToolbarView(self, gifButtonDidPressed: sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func atButtonDidPressed(_ sender: UIButton) {
|
||||||
|
delegate?.composeToolbarView(self, atButtonDidPressed: sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func topicButtonDidPressed(_ sender: UIButton) {
|
||||||
|
delegate?.composeToolbarView(self, topicButtonDidPressed: sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
@objc private func locationButtonDidPressed(_ sender: UIButton) {
|
||||||
|
delegate?.composeToolbarView(self, locationButtonDidPressed: sender)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#if canImport(SwiftUI) && DEBUG
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ComposeToolbarView_Previews: PreviewProvider {
|
||||||
|
|
||||||
|
static var previews: some View {
|
||||||
|
UIViewPreview(width: 375) {
|
||||||
|
let tootbarView = ComposeToolbarView()
|
||||||
|
tootbarView.translatesAutoresizingMaskIntoConstraints = false
|
||||||
|
NSLayoutConstraint.activate([
|
||||||
|
tootbarView.widthAnchor.constraint(equalToConstant: 375).priority(.defaultHigh),
|
||||||
|
tootbarView.heightAnchor.constraint(equalToConstant: 64).priority(.defaultHigh),
|
||||||
|
])
|
||||||
|
return tootbarView
|
||||||
|
}
|
||||||
|
.previewLayout(.fixed(width: 375, height: 100))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
|
@ -351,7 +351,7 @@ extension MastodonRegisterViewController {
|
||||||
|
|
||||||
Publishers.CombineLatest(
|
Publishers.CombineLatest(
|
||||||
KeyboardResponderService.shared.state.eraseToAnyPublisher(),
|
KeyboardResponderService.shared.state.eraseToAnyPublisher(),
|
||||||
KeyboardResponderService.shared.willEndFrame.eraseToAnyPublisher()
|
KeyboardResponderService.shared.endFrame.eraseToAnyPublisher()
|
||||||
)
|
)
|
||||||
.sink(receiveValue: { [weak self] state, endFrame in
|
.sink(receiveValue: { [weak self] state, endFrame in
|
||||||
guard let self = self else { return }
|
guard let self = self else { return }
|
||||||
|
|
|
@ -18,8 +18,7 @@ final class KeyboardResponderService {
|
||||||
// output
|
// output
|
||||||
let isShow = CurrentValueSubject<Bool, Never>(false)
|
let isShow = CurrentValueSubject<Bool, Never>(false)
|
||||||
let state = CurrentValueSubject<KeyboardState, Never>(.none)
|
let state = CurrentValueSubject<KeyboardState, Never>(.none)
|
||||||
let didEndFrame = CurrentValueSubject<CGRect, Never>(.zero)
|
let endFrame = CurrentValueSubject<CGRect, Never>(.zero)
|
||||||
let willEndFrame = CurrentValueSubject<CGRect, Never>(.zero)
|
|
||||||
|
|
||||||
private init() {
|
private init() {
|
||||||
NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification, object: nil)
|
NotificationCenter.default.publisher(for: UIResponder.keyboardWillShowNotification, object: nil)
|
||||||
|
@ -38,15 +37,11 @@ final class KeyboardResponderService {
|
||||||
|
|
||||||
NotificationCenter.default.publisher(for: UIResponder.keyboardDidChangeFrameNotification, object: nil)
|
NotificationCenter.default.publisher(for: UIResponder.keyboardDidChangeFrameNotification, object: nil)
|
||||||
.sink { notification in
|
.sink { notification in
|
||||||
guard let endFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
|
|
||||||
self.didEndFrame.value = endFrame
|
|
||||||
self.updateInternalStatus(notification: notification)
|
self.updateInternalStatus(notification: notification)
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification, object: nil)
|
NotificationCenter.default.publisher(for: UIResponder.keyboardWillChangeFrameNotification, object: nil)
|
||||||
.sink { notification in
|
.sink { notification in
|
||||||
guard let endFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect else { return }
|
|
||||||
self.willEndFrame.value = endFrame
|
|
||||||
self.updateInternalStatus(notification: notification)
|
self.updateInternalStatus(notification: notification)
|
||||||
}
|
}
|
||||||
.store(in: &disposeBag)
|
.store(in: &disposeBag)
|
||||||
|
@ -62,6 +57,8 @@ extension KeyboardResponderService {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.endFrame.value = endFrame
|
||||||
|
|
||||||
guard isLocal else {
|
guard isLocal else {
|
||||||
self.state.value = .notLocal
|
self.state.value = .notLocal
|
||||||
return
|
return
|
||||||
|
|
Loading…
Reference in New Issue