feat: update compose scene UI appearance
@ -240,6 +240,7 @@
|
||||
},
|
||||
"content_input_placeholder": "Type or paste what's on your mind",
|
||||
"compose_action": "Publish",
|
||||
"replying_to_user": "replying to %s",
|
||||
"attachment": {
|
||||
"photo": "photo",
|
||||
"video": "video",
|
||||
@ -254,7 +255,8 @@
|
||||
"six_hours": "6 Hours",
|
||||
"one_day": "1 Day",
|
||||
"three_days": "3 Days",
|
||||
"seven_days": "7 Days"
|
||||
"seven_days": "7 Days",
|
||||
"option_number": "Option %ld"
|
||||
},
|
||||
"content_warning": {
|
||||
"placeholder": "Write an accurate warning here..."
|
||||
@ -336,4 +338,4 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -7,7 +7,7 @@
|
||||
<key>CoreDataStack.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
<key>orderHint</key>
|
||||
<integer>10</integer>
|
||||
<integer>20</integer>
|
||||
</dict>
|
||||
<key>Mastodon - RTL.xcscheme_^#shared#^_</key>
|
||||
<dict>
|
||||
|
@ -50,8 +50,15 @@ extension ComposeStatusSection {
|
||||
weak composeStatusPollExpiresOptionCollectionViewCellDelegate
|
||||
] collectionView, indexPath, item -> UICollectionViewCell? in
|
||||
switch item {
|
||||
case .replyTo(let repliedToStatusObjectID):
|
||||
case .replyTo(let replyToStatusObjectID):
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeRepliedToStatusContentCollectionViewCell.self), for: indexPath) as! ComposeRepliedToStatusContentCollectionViewCell
|
||||
managedObjectContext.perform {
|
||||
guard let replyTo = managedObjectContext.object(with: replyToStatusObjectID) as? Status else {
|
||||
return
|
||||
}
|
||||
let status = replyTo.reblog ?? replyTo
|
||||
cell.statusView.configure(with: AvatarConfigurableViewConfiguration(avatarImageURL: status.author.avatarImageURL()))
|
||||
}
|
||||
return cell
|
||||
case .input(let replyToStatusObjectID, let attribute):
|
||||
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: String(describing: ComposeStatusContentCollectionViewCell.self), for: indexPath) as! ComposeStatusContentCollectionViewCell
|
||||
@ -63,9 +70,10 @@ extension ComposeStatusSection {
|
||||
return
|
||||
}
|
||||
cell.statusView.headerContainerStackView.isHidden = false
|
||||
cell.statusView.headerInfoLabel.text = "[TODO] \(replyTo.author.displayName)"
|
||||
cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.replyIconImage)
|
||||
cell.statusView.headerInfoLabel.text = L10n.Scene.Compose.replyingToUser(replyTo.author.displayNameWithFallback)
|
||||
}
|
||||
ComposeStatusSection.configure(cell: cell, attribute: attribute)
|
||||
ComposeStatusSection.configureStatusContent(cell: cell, attribute: attribute)
|
||||
cell.textEditorView.textAttributesDelegate = textEditorViewTextAttributesDelegate
|
||||
cell.composeContent
|
||||
.removeDuplicates()
|
||||
@ -196,7 +204,7 @@ extension ComposeStatusSection {
|
||||
|
||||
extension ComposeStatusSection {
|
||||
|
||||
static func configure(
|
||||
static func configureStatusContent(
|
||||
cell: ComposeStatusContentCollectionViewCell,
|
||||
attribute: ComposeStatusItem.ComposeStatusAttribute
|
||||
) {
|
||||
|
@ -393,7 +393,7 @@ extension StatusSection {
|
||||
) {
|
||||
if status.reblog != nil {
|
||||
cell.statusView.headerContainerStackView.isHidden = false
|
||||
cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.boostIconImage)
|
||||
cell.statusView.headerIconLabel.attributedText = StatusView.iconAttributedString(image: StatusView.reblogIconImage)
|
||||
cell.statusView.headerInfoLabel.text = {
|
||||
let author = status.author
|
||||
let name = author.displayName.isEmpty ? author.username : author.displayName
|
||||
|
@ -91,26 +91,32 @@ internal enum Asset {
|
||||
internal enum Connectivity {
|
||||
internal static let photoFillSplit = ImageAsset(name: "Connectivity/photo.fill.split")
|
||||
}
|
||||
internal enum Profile {
|
||||
internal enum Banner {
|
||||
internal static let bioEditBackgroundGray = ColorAsset(name: "Profile/Banner/bio.edit.background.gray")
|
||||
internal static let nameEditBackgroundGray = ColorAsset(name: "Profile/Banner/name.edit.background.gray")
|
||||
internal static let usernameGray = ColorAsset(name: "Profile/Banner/username.gray")
|
||||
internal enum Scene {
|
||||
internal enum Compose {
|
||||
internal static let background = ColorAsset(name: "Scene/Compose/background")
|
||||
internal static let toolbarBackground = ColorAsset(name: "Scene/Compose/toolbar.background")
|
||||
}
|
||||
}
|
||||
internal enum Welcome {
|
||||
internal enum Illustration {
|
||||
internal static let backgroundCyan = ColorAsset(name: "Welcome/illustration/background.cyan")
|
||||
internal static let cloudBase = ImageAsset(name: "Welcome/illustration/cloud.base")
|
||||
internal static let elephantOnAirplaneWithContrail = ImageAsset(name: "Welcome/illustration/elephant.on.airplane.with.contrail")
|
||||
internal static let elephantThreeOnGrass = ImageAsset(name: "Welcome/illustration/elephant.three.on.grass")
|
||||
internal static let elephantThreeOnGrassWithTreeThree = ImageAsset(name: "Welcome/illustration/elephant.three.on.grass.with.tree.three")
|
||||
internal static let elephantThreeOnGrassWithTreeTwo = ImageAsset(name: "Welcome/illustration/elephant.three.on.grass.with.tree.two")
|
||||
internal enum Profile {
|
||||
internal enum Banner {
|
||||
internal static let bioEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/bio.edit.background.gray")
|
||||
internal static let nameEditBackgroundGray = ColorAsset(name: "Scene/Profile/Banner/name.edit.background.gray")
|
||||
internal static let usernameGray = ColorAsset(name: "Scene/Profile/Banner/username.gray")
|
||||
}
|
||||
}
|
||||
internal enum Welcome {
|
||||
internal enum Illustration {
|
||||
internal static let backgroundCyan = ColorAsset(name: "Scene/Welcome/illustration/background.cyan")
|
||||
internal static let cloudBase = ImageAsset(name: "Scene/Welcome/illustration/cloud.base")
|
||||
internal static let elephantOnAirplaneWithContrail = ImageAsset(name: "Scene/Welcome/illustration/elephant.on.airplane.with.contrail")
|
||||
internal static let elephantThreeOnGrass = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass")
|
||||
internal static let elephantThreeOnGrassWithTreeThree = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass.with.tree.three")
|
||||
internal static let elephantThreeOnGrassWithTreeTwo = ImageAsset(name: "Scene/Welcome/illustration/elephant.three.on.grass.with.tree.two")
|
||||
}
|
||||
internal static let mastodonLogoBlack = ImageAsset(name: "Scene/Welcome/mastodon.logo.black")
|
||||
internal static let mastodonLogoBlackLarge = ImageAsset(name: "Scene/Welcome/mastodon.logo.black.large")
|
||||
internal static let mastodonLogo = ImageAsset(name: "Scene/Welcome/mastodon.logo")
|
||||
internal static let mastodonLogoLarge = ImageAsset(name: "Scene/Welcome/mastodon.logo.large")
|
||||
}
|
||||
internal static let mastodonLogoBlack = ImageAsset(name: "Welcome/mastodon.logo.black")
|
||||
internal static let mastodonLogoBlackLarge = ImageAsset(name: "Welcome/mastodon.logo.black.large")
|
||||
internal static let mastodonLogo = ImageAsset(name: "Welcome/mastodon.logo")
|
||||
internal static let mastodonLogoLarge = ImageAsset(name: "Welcome/mastodon.logo.large")
|
||||
}
|
||||
}
|
||||
// swiftlint:enable identifier_name line_length nesting type_body_length type_name
|
||||
|
@ -224,6 +224,10 @@ internal enum L10n {
|
||||
internal static let composeAction = L10n.tr("Localizable", "Scene.Compose.ComposeAction")
|
||||
/// Type or paste what's on your mind
|
||||
internal static let contentInputPlaceholder = L10n.tr("Localizable", "Scene.Compose.ContentInputPlaceholder")
|
||||
/// replying to %@
|
||||
internal static func replyingToUser(_ p1: Any) -> String {
|
||||
return L10n.tr("Localizable", "Scene.Compose.ReplyingToUser", String(describing: p1))
|
||||
}
|
||||
internal enum Attachment {
|
||||
/// This %@ is broken and can't be\nuploaded to Mastodon.
|
||||
internal static func attachmentBroken(_ p1: Any) -> String {
|
||||
@ -259,6 +263,10 @@ internal enum L10n {
|
||||
internal static let oneDay = L10n.tr("Localizable", "Scene.Compose.Poll.OneDay")
|
||||
/// 1 Hour
|
||||
internal static let oneHour = L10n.tr("Localizable", "Scene.Compose.Poll.OneHour")
|
||||
/// Option %ld
|
||||
internal static func optionNumber(_ p1: Int) -> String {
|
||||
return L10n.tr("Localizable", "Scene.Compose.Poll.OptionNumber", p1)
|
||||
}
|
||||
/// 7 Days
|
||||
internal static let sevenDays = L10n.tr("Localizable", "Scene.Compose.Poll.SevenDays")
|
||||
/// 6 Hours
|
||||
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "1.000",
|
||||
"green" : "1.000",
|
||||
"red" : "1.000"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "0x1E",
|
||||
"green" : "0x1C",
|
||||
"red" : "0x1C"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,38 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "222",
|
||||
"green" : "216",
|
||||
"red" : "214"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"color" : {
|
||||
"color-space" : "srgb",
|
||||
"components" : {
|
||||
"alpha" : "1.000",
|
||||
"blue" : "43",
|
||||
"green" : "43",
|
||||
"red" : "43"
|
||||
}
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"provides-namespace" : true
|
||||
}
|
||||
}
|
@ -0,0 +1,9 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
},
|
||||
"properties" : {
|
||||
"provides-namespace" : true
|
||||
}
|
||||
}
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
Before Width: | Height: | Size: 58 KiB After Width: | Height: | Size: 58 KiB |
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 16 KiB |
Before Width: | Height: | Size: 44 KiB After Width: | Height: | Size: 44 KiB |
Before Width: | Height: | Size: 82 KiB After Width: | Height: | Size: 82 KiB |
Before Width: | Height: | Size: 46 KiB After Width: | Height: | Size: 46 KiB |
Before Width: | Height: | Size: 130 KiB After Width: | Height: | Size: 130 KiB |
Before Width: | Height: | Size: 238 KiB After Width: | Height: | Size: 238 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 116 KiB After Width: | Height: | Size: 116 KiB |
Before Width: | Height: | Size: 23 KiB After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 64 KiB After Width: | Height: | Size: 64 KiB |
Before Width: | Height: | Size: 118 KiB After Width: | Height: | Size: 118 KiB |
@ -86,10 +86,12 @@ uploaded to Mastodon.";
|
||||
"Scene.Compose.Poll.DurationTime" = "Duration: %@";
|
||||
"Scene.Compose.Poll.OneDay" = "1 Day";
|
||||
"Scene.Compose.Poll.OneHour" = "1 Hour";
|
||||
"Scene.Compose.Poll.OptionNumber" = "Option %ld";
|
||||
"Scene.Compose.Poll.SevenDays" = "7 Days";
|
||||
"Scene.Compose.Poll.SixHours" = "6 Hours";
|
||||
"Scene.Compose.Poll.ThirtyMinutes" = "30 minutes";
|
||||
"Scene.Compose.Poll.ThreeDays" = "3 Days";
|
||||
"Scene.Compose.ReplyingToUser" = "replying to %@";
|
||||
"Scene.Compose.Title.NewPost" = "New Post";
|
||||
"Scene.Compose.Title.NewReply" = "New Reply";
|
||||
"Scene.Compose.Visibility.Direct" = "Only people I mention";
|
||||
|
@ -6,9 +6,22 @@
|
||||
//
|
||||
|
||||
import UIKit
|
||||
import Combine
|
||||
|
||||
final class ComposeRepliedToStatusContentCollectionViewCell: UICollectionViewCell {
|
||||
|
||||
var disposeBag = Set<AnyCancellable>()
|
||||
|
||||
let statusView = StatusView()
|
||||
|
||||
override func prepareForReuse() {
|
||||
super.prepareForReuse()
|
||||
|
||||
statusView.isStatusTextSensitive = false
|
||||
statusView.cleanUpContentWarning()
|
||||
disposeBag.removeAll()
|
||||
}
|
||||
|
||||
override init(frame: CGRect) {
|
||||
super.init(frame: frame)
|
||||
_init()
|
||||
@ -24,7 +37,19 @@ final class ComposeRepliedToStatusContentCollectionViewCell: UICollectionViewCel
|
||||
extension ComposeRepliedToStatusContentCollectionViewCell {
|
||||
|
||||
private func _init() {
|
||||
backgroundColor = .clear
|
||||
statusView.contentWarningBlurContentImageView.backgroundColor = Asset.Scene.Compose.background.color
|
||||
|
||||
statusView.translatesAutoresizingMaskIntoConstraints = false
|
||||
contentView.addSubview(statusView)
|
||||
NSLayoutConstraint.activate([
|
||||
statusView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
|
||||
statusView.leadingAnchor.constraint(equalTo: contentView.readableContentGuide.leadingAnchor),
|
||||
contentView.readableContentGuide.trailingAnchor.constraint(equalTo: statusView.trailingAnchor),
|
||||
contentView.bottomAnchor.constraint(equalTo: statusView.bottomAnchor),
|
||||
])
|
||||
|
||||
statusView.actionToolbarContainer.isHidden = true
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -31,7 +31,7 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
||||
button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.normal.color.withAlphaComponent(0.5)), for: .highlighted)
|
||||
button.setBackgroundImage(.placeholder(color: Asset.Colors.Button.disabled.color), for: .disabled)
|
||||
button.setTitleColor(.white, for: .normal)
|
||||
button.contentEdgeInsets = UIEdgeInsets(top: 3, left: 16, bottom: 3, right: 16)
|
||||
button.contentEdgeInsets = UIEdgeInsets(top: 5.5, left: 16, bottom: 5.5, right: 16) // set 28pt height
|
||||
button.adjustsImageWhenHighlighted = false
|
||||
return button
|
||||
}()
|
||||
@ -66,18 +66,18 @@ final class ComposeViewController: UIViewController, NeedsDependency {
|
||||
return view
|
||||
}()
|
||||
|
||||
let composeToolbarView: ComposeToolbarView = {
|
||||
let composeToolbarView = ComposeToolbarView()
|
||||
let text = UITextView()
|
||||
let inputView = UIInputView(frame: .init(x: 0, y: 0, width: 40, height: 40), inputViewStyle: .keyboard)
|
||||
text.inputAccessoryView = inputView
|
||||
composeToolbarView.backgroundColor = inputView.backgroundColor
|
||||
return composeToolbarView
|
||||
}()
|
||||
let composeToolbarView = ComposeToolbarView()
|
||||
var composeToolbarViewBottomLayoutConstraint: NSLayoutConstraint!
|
||||
let composeToolbarBackgroundView: UIView = {
|
||||
let backgroundView = UIView()
|
||||
backgroundView.backgroundColor = .secondarySystemBackground
|
||||
// set keyboard background to make the keyboard blurred color fixed
|
||||
backgroundView.backgroundColor = UIColor(dynamicProvider: { traitCollection -> UIColor in
|
||||
// avoid elevated color
|
||||
switch traitCollection.userInterfaceStyle {
|
||||
case .light: return .white
|
||||
default: return .black
|
||||
}
|
||||
})
|
||||
return backgroundView
|
||||
}()
|
||||
|
||||
@ -135,7 +135,7 @@ extension ComposeViewController {
|
||||
self.title = title
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
view.backgroundColor = Asset.Colors.Background.systemBackground.color
|
||||
view.backgroundColor = Asset.Scene.Compose.background.color
|
||||
navigationItem.leftBarButtonItem = UIBarButtonItem(title: L10n.Common.Controls.Actions.cancel, style: .plain, target: self, action: #selector(ComposeViewController.cancelBarButtonItemPressed(_:)))
|
||||
navigationItem.rightBarButtonItem = publishBarButtonItem
|
||||
publishButton.addTarget(self, action: #selector(ComposeViewController.publishBarButtonItemPressed(_:)), for: .touchUpInside)
|
||||
@ -266,13 +266,17 @@ extension ComposeViewController {
|
||||
.store(in: &disposeBag)
|
||||
|
||||
// bind visibility toolbar UI
|
||||
viewModel.selectedStatusVisibility
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] type in
|
||||
guard let self = self else { return }
|
||||
self.composeToolbarView.visibilityButton.setImage(type.image, for: .normal)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
Publishers.CombineLatest(
|
||||
viewModel.selectedStatusVisibility,
|
||||
viewModel.traitCollectionDidChangePublisher
|
||||
)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] type, _ in
|
||||
guard let self = self else { return }
|
||||
let image = type.image(interfaceStyle: self.traitCollection.userInterfaceStyle)
|
||||
self.composeToolbarView.visibilityButton.setImage(image, for: .normal)
|
||||
}
|
||||
.store(in: &disposeBag)
|
||||
|
||||
viewModel.characterCount
|
||||
.receive(on: DispatchQueue.main)
|
||||
@ -336,6 +340,12 @@ extension ComposeViewController {
|
||||
}
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
|
||||
viewModel.traitCollectionDidChangePublisher.send()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ComposeViewController {
|
||||
|
@ -29,6 +29,7 @@ final class ComposeViewModel {
|
||||
let selectedStatusVisibility = CurrentValueSubject<ComposeToolbarView.VisibilitySelectionType, Never>(.public)
|
||||
let activeAuthentication: CurrentValueSubject<MastodonAuthentication?, Never>
|
||||
let activeAuthenticationBox: CurrentValueSubject<AuthenticationService.MastodonAuthenticationBox?, Never>
|
||||
let traitCollectionDidChangePublisher = PassthroughSubject<Void, Never>()
|
||||
|
||||
// output
|
||||
var diffableDataSource: UICollectionViewDiffableDataSource<ComposeStatusSection, ComposeStatusItem>!
|
||||
|
@ -80,8 +80,12 @@ final class ComposeToolbarView: UIView {
|
||||
}
|
||||
|
||||
extension ComposeToolbarView {
|
||||
|
||||
private func _init() {
|
||||
backgroundColor = .secondarySystemBackground
|
||||
// magic keyboard color (iOS 14):
|
||||
// light with white background: RGB 214 216 222
|
||||
// dark with black background: RGB 43 43 43
|
||||
backgroundColor = Asset.Scene.Compose.toolbarBackground.color
|
||||
|
||||
let stackView = UIStackView()
|
||||
stackView.axis = .horizontal
|
||||
@ -125,9 +129,18 @@ extension ComposeToolbarView {
|
||||
pollButton.addTarget(self, action: #selector(ComposeToolbarView.pollButtonDidPressed(_:)), for: .touchUpInside)
|
||||
emojiButton.addTarget(self, action: #selector(ComposeToolbarView.emojiButtonDidPressed(_:)), for: .touchUpInside)
|
||||
contentWarningButton.addTarget(self, action: #selector(ComposeToolbarView.contentWarningButtonDidPressed(_:)), for: .touchUpInside)
|
||||
visibilityButton.menu = createVisibilityContextMenu()
|
||||
visibilityButton.menu = createVisibilityContextMenu(interfaceStyle: traitCollection.userInterfaceStyle)
|
||||
visibilityButton.showsMenuAsPrimaryAction = true
|
||||
|
||||
updateToolbarButtonUserInterfaceStyle()
|
||||
}
|
||||
|
||||
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
|
||||
super.traitCollectionDidChange(previousTraitCollection)
|
||||
|
||||
updateToolbarButtonUserInterfaceStyle()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extension ComposeToolbarView {
|
||||
@ -152,9 +165,15 @@ extension ComposeToolbarView {
|
||||
}
|
||||
}
|
||||
|
||||
var image: UIImage {
|
||||
func image(interfaceStyle: UIUserInterfaceStyle) -> UIImage {
|
||||
switch self {
|
||||
case .public: return UIImage(systemName: "person.3", withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .medium))!
|
||||
case .public:
|
||||
switch interfaceStyle {
|
||||
case .light:
|
||||
return UIImage(systemName: "person.3", withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .medium))!
|
||||
default:
|
||||
return UIImage(systemName: "person.3.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 15, weight: .medium))!
|
||||
}
|
||||
case .unlisted: return UIImage(systemName: "eye.slash", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .medium))!
|
||||
case .private: return UIImage(systemName: "person.crop.circle.badge.plus", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .medium))!
|
||||
case .direct: return UIImage(systemName: "at", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .medium))!
|
||||
@ -182,6 +201,25 @@ extension ComposeToolbarView {
|
||||
button.layer.cornerCurve = .continuous
|
||||
}
|
||||
|
||||
private func updateToolbarButtonUserInterfaceStyle() {
|
||||
switch traitCollection.userInterfaceStyle {
|
||||
case .light:
|
||||
mediaButton.setImage(UIImage(systemName: "photo", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
emojiButton.setImage(UIImage(systemName: "face.smiling", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
contentWarningButton.setImage(UIImage(systemName: "exclamationmark.shield", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
|
||||
case .dark:
|
||||
mediaButton.setImage(UIImage(systemName: "photo.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
emojiButton.setImage(UIImage(systemName: "face.smiling.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
contentWarningButton.setImage(UIImage(systemName: "exclamationmark.shield.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 20, weight: .regular))!, for: .normal)
|
||||
|
||||
default:
|
||||
assertionFailure()
|
||||
}
|
||||
|
||||
visibilityButton.menu = createVisibilityContextMenu(interfaceStyle: traitCollection.userInterfaceStyle)
|
||||
}
|
||||
|
||||
private func createMediaContextMenu() -> UIMenu {
|
||||
var children: [UIMenuElement] = []
|
||||
let photoLibraryAction = UIAction(title: L10n.Scene.Compose.MediaSelection.photoLibrary, image: UIImage(systemName: "rectangle.on.rectangle"), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] _ in
|
||||
@ -208,9 +246,9 @@ extension ComposeToolbarView {
|
||||
return UIMenu(title: "", image: nil, identifier: nil, options: .displayInline, children: children)
|
||||
}
|
||||
|
||||
private func createVisibilityContextMenu() -> UIMenu {
|
||||
private func createVisibilityContextMenu(interfaceStyle: UIUserInterfaceStyle) -> UIMenu {
|
||||
let children: [UIMenuElement] = VisibilitySelectionType.allCases.map { type in
|
||||
UIAction(title: type.title, image: type.image, identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] action in
|
||||
UIAction(title: type.title, image: type.image(interfaceStyle: interfaceStyle), identifier: nil, discoverabilityTitle: nil, attributes: [], state: .off) { [weak self] action in
|
||||
guard let self = self else { return }
|
||||
os_log(.info, log: .debug, "%{public}s[%{public}ld], %{public}s: visibilitySelectionType: %s", ((#file as NSString).lastPathComponent), #line, #function, type.rawValue)
|
||||
self.delegate?.composeToolbarView(self, visibilityButtonDidPressed: self.visibilityButton, visibilitySelectionType: type)
|
||||
|
@ -16,14 +16,14 @@ final class WelcomeIllustrationView: UIView {
|
||||
let leftHillImageView = UIImageView()
|
||||
let centerHillImageView = UIImageView()
|
||||
|
||||
private let cloudBaseImage = Asset.Welcome.Illustration.cloudBase.image
|
||||
private let elephantThreeOnGrassWithTreeTwoImage = Asset.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image
|
||||
private let elephantThreeOnGrassWithTreeThreeImage = Asset.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image
|
||||
private let elephantThreeOnGrassImage = Asset.Welcome.Illustration.elephantThreeOnGrass.image
|
||||
private let cloudBaseImage = Asset.Scene.Welcome.Illustration.cloudBase.image
|
||||
private let elephantThreeOnGrassWithTreeTwoImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeTwo.image
|
||||
private let elephantThreeOnGrassWithTreeThreeImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrassWithTreeThree.image
|
||||
private let elephantThreeOnGrassImage = Asset.Scene.Welcome.Illustration.elephantThreeOnGrass.image
|
||||
|
||||
// layout outside
|
||||
let elephantOnAirplaneWithContrailImageView: UIImageView = {
|
||||
let imageView = UIImageView(image: Asset.Welcome.Illustration.elephantOnAirplaneWithContrail.image)
|
||||
let imageView = UIImageView(image: Asset.Scene.Welcome.Illustration.elephantOnAirplaneWithContrail.image)
|
||||
imageView.contentMode = .scaleAspectFill
|
||||
return imageView
|
||||
}()
|
||||
@ -43,7 +43,7 @@ final class WelcomeIllustrationView: UIView {
|
||||
extension WelcomeIllustrationView {
|
||||
|
||||
private func _init() {
|
||||
backgroundColor = Asset.Welcome.Illustration.backgroundCyan.color
|
||||
backgroundColor = Asset.Scene.Welcome.Illustration.backgroundCyan.color
|
||||
|
||||
let topPaddingView = UIView()
|
||||
|
||||
|
@ -17,7 +17,7 @@ final class WelcomeViewController: UIViewController, NeedsDependency {
|
||||
var welcomeIllustrationViewBottomAnchorLayoutConstraint: NSLayoutConstraint?
|
||||
|
||||
private(set) lazy var logoImageView: UIImageView = {
|
||||
let image = view.traitCollection.userInterfaceIdiom == .phone ? Asset.Welcome.mastodonLogo.image : Asset.Welcome.mastodonLogoBlackLarge.image
|
||||
let image = view.traitCollection.userInterfaceIdiom == .phone ? Asset.Scene.Welcome.mastodonLogo.image : Asset.Scene.Welcome.mastodonLogoBlackLarge.image
|
||||
let imageView = UIImageView(image: image)
|
||||
imageView.translatesAutoresizingMaskIntoConstraints = false
|
||||
return imageView
|
||||
|
@ -100,7 +100,7 @@ final class ProfileHeaderView: UIView {
|
||||
label.font = UIFontMetrics(forTextStyle: .subheadline).scaledFont(for: .systemFont(ofSize: 15, weight: .regular))
|
||||
label.adjustsFontSizeToFitWidth = true
|
||||
label.minimumScaleFactor = 0.5
|
||||
label.textColor = Asset.Profile.Banner.usernameGray.color
|
||||
label.textColor = Asset.Scene.Profile.Banner.usernameGray.color
|
||||
label.text = "@alice"
|
||||
label.applyShadow(color: UIColor.black.withAlphaComponent(0.2), alpha: 0.5, x: 0, y: 2, blur: 2, spread: 0)
|
||||
return label
|
||||
@ -131,7 +131,7 @@ final class ProfileHeaderView: UIView {
|
||||
textEditorView.scrollView.isScrollEnabled = false
|
||||
textEditorView.isScrollEnabled = false
|
||||
textEditorView.font = .preferredFont(forTextStyle: .body)
|
||||
textEditorView.backgroundColor = Asset.Profile.Banner.bioEditBackgroundGray.color
|
||||
textEditorView.backgroundColor = Asset.Scene.Profile.Banner.bioEditBackgroundGray.color
|
||||
textEditorView.layer.masksToBounds = true
|
||||
textEditorView.layer.cornerCurve = .continuous
|
||||
textEditorView.layer.cornerRadius = 10
|
||||
@ -356,9 +356,9 @@ extension ProfileHeaderView {
|
||||
bioTextEditorView.backgroundColor = .clear
|
||||
animator.addAnimations {
|
||||
self.bannerImageViewOverlayView.backgroundColor = ProfileHeaderView.bannerImageViewOverlayViewBackgroundEditingColor
|
||||
self.nameTextFieldBackgroundView.backgroundColor = Asset.Profile.Banner.nameEditBackgroundGray.color
|
||||
self.nameTextFieldBackgroundView.backgroundColor = Asset.Scene.Profile.Banner.nameEditBackgroundGray.color
|
||||
self.editAvatarBackgroundView.alpha = 1
|
||||
self.bioTextEditorView.backgroundColor = Asset.Profile.Banner.bioEditBackgroundGray.color
|
||||
self.bioTextEditorView.backgroundColor = Asset.Scene.Profile.Banner.bioEditBackgroundGray.color
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -29,7 +29,7 @@ final class StatusView: UIView {
|
||||
static let avatarToLabelSpacing: CGFloat = 5
|
||||
static let contentWarningBlurRadius: CGFloat = 12
|
||||
|
||||
static let boostIconImage: UIImage = {
|
||||
static let reblogIconImage: UIImage = {
|
||||
let font = UIFont.systemFont(ofSize: 13, weight: .medium)
|
||||
let configuration = UIImage.SymbolConfiguration(font: font)
|
||||
let image = UIImage(systemName: "arrow.2.squarepath", withConfiguration: configuration)!.withTintColor(Asset.Colors.Label.secondary.color)
|
||||
@ -61,7 +61,7 @@ final class StatusView: UIView {
|
||||
|
||||
let headerIconLabel: UILabel = {
|
||||
let label = UILabel()
|
||||
label.attributedText = StatusView.iconAttributedString(image: StatusView.boostIconImage)
|
||||
label.attributedText = StatusView.iconAttributedString(image: StatusView.reblogIconImage)
|
||||
return label
|
||||
}()
|
||||
|
||||
|