Skip to content

Commit

Permalink
feat: add ornament for NewPostVC
Browse files Browse the repository at this point in the history
  • Loading branch information
rinsuki committed Feb 12, 2024
1 parent da3e32b commit 484c0c5
Show file tree
Hide file tree
Showing 6 changed files with 342 additions and 175 deletions.
6 changes: 5 additions & 1 deletion Sources/Core/Mastodon/API/MastodonPostVisibility.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,16 @@ import Foundation
import UIKit
#endif

public enum MastodonPostVisibility: String, CaseIterable, Codable, Sendable {
public enum MastodonPostVisibility: String, CaseIterable, Codable, Sendable, Identifiable {
case `public`
case unlisted
case `private`
case direct

public var id: String {
rawValue
}

public var localizedName: String {
switch self {
case .public:
Expand Down
136 changes: 77 additions & 59 deletions Sources/iOS/App/Screens/NewPost/NewPostMediaListViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,17 +30,19 @@ import Ikemen
import iMastiOSCore

class NewPostMediaListViewController: UIViewController {

let newPostVC: NewPostViewController
let viewModel: NewPostViewModel
var inline: Bool

// TODO: contact じゃないのに使っていいの? アクセシビリティ周りマズそう
let addButton = UIButton(type: .contactAdd)
let imagesStackView = UIStackView() { v in
v.distribution = .fillEqually
v.alignment = .leading
}

init(newPostVC: NewPostViewController) {
self.newPostVC = newPostVC
init(viewModel: NewPostViewModel, inline: Bool) {
self.viewModel = viewModel
self.inline = inline
super.init(nibName: nil, bundle: nil)
}

Expand All @@ -52,57 +54,61 @@ class NewPostMediaListViewController: UIViewController {
super.viewDidLoad()

// Do any additional setup after loading the view.
let stackView = UIStackView(arrangedSubviews: [
addButton,
imagesStackView,
])
stackView.spacing = 8
view.addSubview(stackView)
stackView.snp.makeConstraints { make in
make.center.equalTo(view.safeAreaLayoutGuide)
make.size.equalTo(view.safeAreaLayoutGuide).inset(8)
}
addButton.snp.makeConstraints { make in
make.width.equalToSuperview().multipliedBy(1/5.0).inset(4)
}

let addFromPhotoLibrary = UIAction(
title: L10n.NewPost.Media.Picker.photoLibrary,
image: UIImage(systemName: "rectangle.on.rectangle"),
handler: { [weak self] _ in
self?.addFromPhotoLibrary()
if inline {
view.addSubview(imagesStackView)
imagesStackView.spacing = 8
imagesStackView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(8)
make.height.equalTo(72)
}
)

#if os(visionOS)
let menu = UIMenu(children: [
addFromPhotoLibrary,
])
#else
let menu = UIMenu(children: [
addFromPhotoLibrary,
UIAction(
title: L10n.NewPost.Media.Picker.takePhoto,
image: UIImage(systemName: "camera.fill"),
handler: { [weak self] _ in
self?.addFromCamera()
}
),
UIAction(
title: "ブラウズ",
image: UIImage(systemName: "ellipsis"),
handler: { [weak self] _ in
guard let strongSelf = self else { return }
let pickerVC = UIDocumentPickerViewController(forOpeningContentTypes: [.image], asCopy: true)
pickerVC.delegate = strongSelf
strongSelf.present(pickerVC, animated: true, completion: nil)
}
),
])
#endif
addButton.preferredMenuElementOrder = .fixed
addButton.menu = menu
addButton.showsMenuAsPrimaryAction = true
} else {
let stackView = UIStackView(arrangedSubviews: [
addButton,
imagesStackView,
])
stackView.spacing = 8
view.addSubview(stackView)
stackView.snp.makeConstraints { make in
make.center.equalTo(view.safeAreaLayoutGuide)
make.size.equalTo(view.safeAreaLayoutGuide).inset(8)
}
addButton.snp.makeConstraints { make in
make.width.equalToSuperview().multipliedBy(1/5.0).inset(4)
}
let menu = UIMenu(children: [
UIAction(
title: L10n.NewPost.Media.Picker.photoLibrary,
image: UIImage(systemName: "rectangle.on.rectangle"),
handler: { [weak self] _ in
self?.addFromPhotoLibrary()
}
),
UIAction(
title: L10n.NewPost.Media.Picker.takePhoto,
image: UIImage(systemName: "camera.fill"),
handler: { [weak self] _ in
#if !os(visionOS)
self?.addFromCamera()
#endif
}
),
UIAction(
title: "ブラウズ",
image: UIImage(systemName: "ellipsis"),
handler: { [weak self] _ in
#if !os(visionOS)
guard let strongSelf = self else { return }
let pickerVC = UIDocumentPickerViewController(forOpeningContentTypes: [.image], asCopy: true)
pickerVC.delegate = strongSelf
strongSelf.present(pickerVC, animated: true, completion: nil)
#endif
}
),
])
addButton.preferredMenuElementOrder = .fixed
addButton.menu = menu
addButton.showsMenuAsPrimaryAction = true
}
self.refresh()
}

Expand All @@ -117,8 +123,8 @@ class NewPostMediaListViewController: UIViewController {
self.imagesStackView.removeArrangedSubview(imageView)
imageView.removeFromSuperview()
}
if self.newPostVC.media.count > 0 {
for (index, media) in self.newPostVC.media.enumerated() {
if viewModel.media.count > 0 {
for (index, media) in viewModel.media.enumerated() {
let imageView = UIImageView(image: media.thumbnailImage)
imageView.ignoreSmartInvert()
imageView.contentMode = .scaleAspectFill
Expand All @@ -128,6 +134,11 @@ class NewPostMediaListViewController: UIViewController {
tapGesture.numberOfTapsRequired = 1
imageView.isUserInteractionEnabled = true
imageView.addGestureRecognizer(tapGesture)
if inline {
imageView.snp.makeConstraints { make in
make.width.equalTo(imageView.snp.height)
}
}
self.imagesStackView.addArrangedSubview(imageView)
}
} else {
Expand All @@ -141,14 +152,19 @@ class NewPostMediaListViewController: UIViewController {
}

func addMedia(media: UploadableMedia) {
self.newPostVC.media.append(media)
viewModel.media.append(media)
self.refresh()
}

func addFromPhotoLibrary() {
let imgPickerC = UIImagePickerController()
imgPickerC.sourceType = .photoLibrary
#if os(visionOS)
// TODO: visionOS でも動画に対応する
imgPickerC.mediaTypes = [kUTTypeImage as String]
#else
imgPickerC.mediaTypes = [kUTTypeMovie as String, kUTTypeImage as String]
#endif
imgPickerC.videoExportPreset = AVAssetExportPresetPassthrough
showImagePickerController(imgPickerC)
}
Expand All @@ -168,7 +184,7 @@ class NewPostMediaListViewController: UIViewController {

@objc func tapCurrentMedia(sender: UITapGestureRecognizer) {
guard let index = sender.view?.tag else { return }
let media = newPostVC.media[index]
let media = viewModel.media[index]

let alertVC = UIAlertController(title: nil, message: nil, preferredStyle: .alert)
alertVC.addAction(UIAlertAction(title: L10n.NewPost.Media.preview, style: .default, handler: { _ in
Expand All @@ -195,7 +211,7 @@ class NewPostMediaListViewController: UIViewController {
}
}))
alertVC.addAction(UIAlertAction(title: L10n.NewPost.Media.delete, style: .destructive, handler: { _ in
self.newPostVC.media.remove(at: index)
self.viewModel.media.remove(at: index)
self.refresh()
}))
alertVC.addAction(UIAlertAction(title: L10n.Localizable.cancel, style: .cancel, handler: nil))
Expand All @@ -204,6 +220,7 @@ class NewPostMediaListViewController: UIViewController {
}
}

// TODO: 新しい document picker の delegate に対応してこちらも開放する
#if !os(visionOS)
extension NewPostMediaListViewController: UIDocumentPickerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
Expand All @@ -221,6 +238,7 @@ extension NewPostMediaListViewController: UIImagePickerControllerDelegate {
let data = try! Data(contentsOf: url, options: NSData.ReadingOptions.mappedIfSafe)
self.addMedia(media: UploadableMedia(format: url.pathExtension.lowercased() == "png" ? .png : .jpeg, data: data, url: nil, thumbnailImage: UIImage(data: data)!))
} else if let url = info[.mediaURL] as? URL {
// TODO: visionOS でも動画投稿に対応する
#if !os(visionOS)
Task {
let asset = AVURLAsset(url: url)
Expand Down
27 changes: 21 additions & 6 deletions Sources/iOS/App/Screens/NewPost/NewPostView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -73,10 +73,10 @@ class NewPostView: UIView {
$0.width = 44
}

convenience init() {
self.init(frame: .zero)
backgroundColor = .systemBackground

let stackView: UIStackView

init() {
#if !os(visionOS)
addSubview(toolBar)
toolBar.items = [
imageSelectItem,
Expand All @@ -88,22 +88,31 @@ class NewPostView: UIView {
make.top.equalTo(safeAreaLayoutGuide.snp.bottom)
make.leading.trailing.equalToSuperview()
}
#endif

let separatorView = SeparatorView()

let stackView = UIStackView(arrangedSubviews: [
stackView = .init(arrangedSubviews: [
cwInput,
separatorView,
textInput,
])
stackView.alignment = .center
stackView.alignment = .leading
stackView.spacing = 0
stackView.axis = .vertical

super.init(frame: .zero)
backgroundColor = .systemBackground

addSubview(stackView)
stackView.snp.makeConstraints { make in
make.leading.trailing.equalToSuperview()
make.top.equalTo(safeAreaLayoutGuide.snp.top)
#if !os(visionOS)
make.bottom.equalTo(toolBar.snp.top)
#else
make.bottom.equalTo(safeAreaLayoutGuide.snp.bottom)
#endif
}
cwInput.snp.makeConstraints { make in
make.leading.trailing.equalTo(safeAreaLayoutGuide)
Expand All @@ -119,6 +128,12 @@ class NewPostView: UIView {
currentAccountLabel.snp.makeConstraints { make in
make.leading.trailing.bottom.equalTo(safeAreaLayoutGuide).inset(8)
}
#if !os(visionOS)
bringSubviewToFront(toolBar)
#endif
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Loading

0 comments on commit 484c0c5

Please sign in to comment.