2022-10-18 13:01:31 +02:00
|
|
|
//
|
|
|
|
// ComposeContentToolbarView.swift
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// Created by MainasuK on 22/10/18.
|
|
|
|
//
|
|
|
|
|
2022-10-21 13:12:44 +02:00
|
|
|
import os.log
|
2022-10-18 13:01:31 +02:00
|
|
|
import SwiftUI
|
|
|
|
import MastodonAsset
|
2022-10-21 13:12:44 +02:00
|
|
|
import MastodonLocalization
|
|
|
|
import MastodonSDK
|
|
|
|
|
|
|
|
protocol ComposeContentToolbarViewDelegate: AnyObject {
|
|
|
|
func composeContentToolbarView(_ viewModel: ComposeContentToolbarView.ViewModel, toolbarItemDidPressed action: ComposeContentToolbarView.ViewModel.Action)
|
|
|
|
func composeContentToolbarView(_ viewModel: ComposeContentToolbarView.ViewModel, attachmentMenuDidPressed action: ComposeContentToolbarView.ViewModel.AttachmentAction)
|
|
|
|
}
|
2022-10-18 13:01:31 +02:00
|
|
|
|
|
|
|
struct ComposeContentToolbarView: View {
|
|
|
|
|
2022-10-21 13:12:44 +02:00
|
|
|
let logger = Logger(subsystem: "ComposeContentToolbarView", category: "View")
|
|
|
|
|
2022-10-18 13:01:31 +02:00
|
|
|
static var toolbarHeight: CGFloat { 48 }
|
|
|
|
|
|
|
|
@ObservedObject var viewModel: ViewModel
|
|
|
|
|
|
|
|
var body: some View {
|
|
|
|
HStack(spacing: .zero) {
|
|
|
|
ForEach(ComposeContentToolbarView.ViewModel.Action.allCases, id: \.self) { action in
|
|
|
|
switch action {
|
|
|
|
case .attachment:
|
|
|
|
Menu {
|
2022-10-21 13:12:44 +02:00
|
|
|
ForEach(ComposeContentToolbarView.ViewModel.AttachmentAction.allCases, id: \.self) { attachmentAction in
|
|
|
|
Button {
|
|
|
|
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public), \(attachmentAction.title)")
|
|
|
|
viewModel.delegate?.composeContentToolbarView(viewModel, attachmentMenuDidPressed: attachmentAction)
|
|
|
|
} label: {
|
|
|
|
Label {
|
|
|
|
Text(attachmentAction.title)
|
|
|
|
} icon: {
|
|
|
|
Image(uiImage: attachmentAction.image)
|
|
|
|
}
|
|
|
|
}
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
} label: {
|
|
|
|
label(for: action)
|
2022-11-13 15:08:26 +01:00
|
|
|
.opacity(viewModel.isAttachmentButtonEnabled ? 1.0 : 0.5)
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
2022-11-13 15:08:26 +01:00
|
|
|
.disabled(!viewModel.isAttachmentButtonEnabled)
|
2022-10-18 13:01:31 +02:00
|
|
|
.frame(width: 48, height: 48)
|
|
|
|
case .visibility:
|
|
|
|
Menu {
|
|
|
|
Picker(selection: $viewModel.visibility) {
|
|
|
|
ForEach(viewModel.allVisibilities, id: \.self) { visibility in
|
2022-10-21 13:12:44 +02:00
|
|
|
Label {
|
|
|
|
Text(visibility.title)
|
|
|
|
} icon: {
|
|
|
|
Image(uiImage: visibility.image)
|
|
|
|
}
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
} label: {
|
2022-10-21 13:12:44 +02:00
|
|
|
Text(viewModel.visibility.title)
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
} label: {
|
2022-10-21 13:12:44 +02:00
|
|
|
label(for: viewModel.visibility.image)
|
2022-11-07 02:49:12 +01:00
|
|
|
.accessibilityLabel(L10n.Scene.Compose.Keyboard.selectVisibilityEntry(viewModel.visibility.title))
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
.frame(width: 48, height: 48)
|
2022-11-13 15:08:26 +01:00
|
|
|
case .poll:
|
|
|
|
Button {
|
|
|
|
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): \(String(describing: action))")
|
|
|
|
viewModel.delegate?.composeContentToolbarView(viewModel, toolbarItemDidPressed: action)
|
|
|
|
} label: {
|
|
|
|
label(for: action)
|
|
|
|
.opacity(viewModel.isPollButtonEnabled ? 1.0 : 0.5)
|
|
|
|
}
|
|
|
|
.disabled(!viewModel.isPollButtonEnabled)
|
|
|
|
.frame(width: 48, height: 48)
|
2022-10-18 13:01:31 +02:00
|
|
|
default:
|
|
|
|
Button {
|
2022-10-21 13:12:44 +02:00
|
|
|
logger.log(level: .debug, "\((#file as NSString).lastPathComponent, privacy: .public)[\(#line, privacy: .public)], \(#function, privacy: .public): \(String(describing: action))")
|
|
|
|
viewModel.delegate?.composeContentToolbarView(viewModel, toolbarItemDidPressed: action)
|
2022-10-18 13:01:31 +02:00
|
|
|
} label: {
|
|
|
|
label(for: action)
|
|
|
|
}
|
|
|
|
.frame(width: 48, height: 48)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
Spacer()
|
2022-10-28 13:06:18 +02:00
|
|
|
let count: Int = {
|
|
|
|
if viewModel.isContentWarningActive {
|
|
|
|
return viewModel.contentWeightedLength + viewModel.contentWarningWeightedLength
|
|
|
|
} else {
|
|
|
|
return viewModel.contentWeightedLength
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
let remains = viewModel.maxTextInputLimit - count
|
|
|
|
let isOverflow = remains < 0
|
|
|
|
Text("\(remains)")
|
|
|
|
.foregroundColor(Color(isOverflow ? UIColor.systemRed : UIColor.secondaryLabel))
|
|
|
|
.font(.system(size: isOverflow ? 18 : 16, weight: isOverflow ? .medium : .regular))
|
2022-11-08 19:50:23 +01:00
|
|
|
.accessibilityLabel(L10n.A11y.Plural.Count.charactersLeft(remains))
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
.padding(.leading, 4) // 4 + 12 = 16
|
|
|
|
.padding(.trailing, 16)
|
|
|
|
.frame(height: ComposeContentToolbarView.toolbarHeight)
|
|
|
|
.background(Color(viewModel.backgroundColor))
|
2022-11-07 02:51:13 +01:00
|
|
|
.accessibilityElement(children: .contain)
|
2022-11-08 19:50:23 +01:00
|
|
|
.accessibilityLabel(L10n.Scene.Compose.Accessibility.postOptions)
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
extension ComposeContentToolbarView {
|
|
|
|
func label(for action: ComposeContentToolbarView.ViewModel.Action) -> some View {
|
2022-10-21 13:12:44 +02:00
|
|
|
Image(uiImage: viewModel.image(for: action))
|
2022-10-18 13:01:31 +02:00
|
|
|
.foregroundColor(Color(Asset.Scene.Compose.buttonTint.color))
|
|
|
|
.frame(width: 24, height: 24, alignment: .center)
|
2022-11-07 02:49:12 +01:00
|
|
|
.accessibilityLabel(viewModel.label(for: action))
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|
2022-10-21 13:12:44 +02:00
|
|
|
|
|
|
|
func label(for image: UIImage) -> some View {
|
|
|
|
Image(uiImage: image)
|
|
|
|
.foregroundColor(Color(Asset.Scene.Compose.buttonTint.color))
|
|
|
|
.frame(width: 24, height: 24, alignment: .center)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
extension Mastodon.Entity.Status.Visibility {
|
|
|
|
fileprivate var title: String {
|
|
|
|
switch self {
|
|
|
|
case .public: return L10n.Scene.Compose.Visibility.public
|
|
|
|
case .unlisted: return L10n.Scene.Compose.Visibility.unlisted
|
|
|
|
case .private: return L10n.Scene.Compose.Visibility.private
|
|
|
|
case .direct: return L10n.Scene.Compose.Visibility.direct
|
|
|
|
case ._other(let value): return value
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fileprivate var image: UIImage {
|
|
|
|
switch self {
|
|
|
|
case .public: return Asset.Scene.Compose.earth.image.withRenderingMode(.alwaysTemplate)
|
|
|
|
case .unlisted: return Asset.Scene.Compose.people.image.withRenderingMode(.alwaysTemplate)
|
|
|
|
case .private: return Asset.Scene.Compose.peopleAdd.image.withRenderingMode(.alwaysTemplate)
|
|
|
|
case .direct: return Asset.Scene.Compose.mention.image.withRenderingMode(.alwaysTemplate)
|
|
|
|
case ._other: return Asset.Scene.Compose.more.image.withRenderingMode(.alwaysTemplate)
|
|
|
|
}
|
|
|
|
}
|
2022-10-18 13:01:31 +02:00
|
|
|
}
|