From 8cc08cf4c0c1da1d7ca7c507c55c4be8871e782e Mon Sep 17 00:00:00 2001 From: Shadowfacts Date: Sun, 1 May 2022 12:22:15 -0400 Subject: [PATCH] Fix crash when displaying polls on Catalyst in Optimize for Mac Closes #152 --- Tusker.xcodeproj/project.pbxproj | 4 ++ Tusker/Views/Poll/PollVoteButton.swift | 79 ++++++++++++++++++++++++++ Tusker/Views/Poll/StatusPollView.swift | 28 +++++---- 3 files changed, 99 insertions(+), 12 deletions(-) create mode 100644 Tusker/Views/Poll/PollVoteButton.swift diff --git a/Tusker.xcodeproj/project.pbxproj b/Tusker.xcodeproj/project.pbxproj index 8ced2977..5594bb0a 100644 --- a/Tusker.xcodeproj/project.pbxproj +++ b/Tusker.xcodeproj/project.pbxproj @@ -236,6 +236,7 @@ D6B81F442560390300F6E31D /* MenuController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B81F432560390300F6E31D /* MenuController.swift */; }; D6B8DB342182A59300424AF7 /* UIAlertController+Visibility.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */; }; D6B93667281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B93666281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift */; }; + D6B9366B281EE77E00237D0E /* PollVoteButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6B9366A281EE77E00237D0E /* PollVoteButton.swift */; }; D6BC8748219738E1006163F1 /* EnhancedTableViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC8747219738E1006163F1 /* EnhancedTableViewController.swift */; }; D6BC9DB1232C61BC002CA326 /* NotificationsPageViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DB0232C61BC002CA326 /* NotificationsPageViewController.swift */; }; D6BC9DB3232D4C07002CA326 /* WellnessPrefsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6BC9DB2232D4C07002CA326 /* WellnessPrefsView.swift */; }; @@ -577,6 +578,7 @@ D6B81F432560390300F6E31D /* MenuController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuController.swift; sourceTree = ""; }; D6B8DB332182A59300424AF7 /* UIAlertController+Visibility.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIAlertController+Visibility.swift"; sourceTree = ""; }; D6B93666281D937300237D0E /* MainSidebarMyProfileCollectionViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MainSidebarMyProfileCollectionViewCell.swift; sourceTree = ""; }; + D6B9366A281EE77E00237D0E /* PollVoteButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PollVoteButton.swift; sourceTree = ""; }; D6BC8747219738E1006163F1 /* EnhancedTableViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = EnhancedTableViewController.swift; sourceTree = ""; }; D6BC9DB0232C61BC002CA326 /* NotificationsPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsPageViewController.swift; sourceTree = ""; }; D6BC9DB2232D4C07002CA326 /* WellnessPrefsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WellnessPrefsView.swift; sourceTree = ""; }; @@ -749,6 +751,7 @@ D6A00B1C26379FC900316AD4 /* PollOptionsView.swift */, D623A5402635FB3C0095BD04 /* PollOptionView.swift */, D623A542263634100095BD04 /* PollOptionCheckboxView.swift */, + D6B9366A281EE77E00237D0E /* PollVoteButton.swift */, ); path = Poll; sourceTree = ""; @@ -1930,6 +1933,7 @@ D68232F72464F4FD00325FB8 /* ComposeDrawingViewController.swift in Sources */, 04586B4122B2FFB10021BD04 /* PreferencesView.swift in Sources */, D6620ACE2511A0ED00312CA0 /* StatusStateResolver.swift in Sources */, + D6B9366B281EE77E00237D0E /* PollVoteButton.swift in Sources */, D6BC9DB5232D4CE3002CA326 /* NotificationsMode.swift in Sources */, D68015402401A6BA00D6103B /* ComposingPrefsView.swift in Sources */, D67895BC24671E6D00D4CD9E /* PKDrawing+Render.swift in Sources */, diff --git a/Tusker/Views/Poll/PollVoteButton.swift b/Tusker/Views/Poll/PollVoteButton.swift new file mode 100644 index 00000000..96fa4f61 --- /dev/null +++ b/Tusker/Views/Poll/PollVoteButton.swift @@ -0,0 +1,79 @@ +// +// PollVoteButton.swift +// Tusker +// +// Created by Shadowfacts on 5/1/22. +// Copyright © 2022 Shadowfacts. All rights reserved. +// + +import UIKit + +/// Wraps a UILabel and UIButton to allow setting disabled titles on Catalyst, where `setTitle(_:for:)` only works for the normal state. +class PollVoteButton: UIView { + + var disabledTitle: String = "" { + didSet { + update() + } + } + var isEnabled = true { + didSet { + update() + } + } + + private var button = UIButton(type: .system) + #if targetEnvironment(macCatalyst) + private var label = UILabel() + #endif + + override init(frame: CGRect) { + super.init(frame: frame) + + button.translatesAutoresizingMaskIntoConstraints = false + button.setTitleColor(.secondaryLabel, for: .disabled) + embedSubview(button) + #if targetEnvironment(macCatalyst) + label.textColor = .secondaryLabel + label.translatesAutoresizingMaskIntoConstraints = false + embedSubview(label) + #endif + + update() + } + + required init?(coder: NSCoder) { + fatalError("init(coder:) has not been implemented") + } + + func addTarget(_ target: Any, action: Selector) { + button.addTarget(target, action: action, for: .touchUpInside) + } + + func setFont(_ font: UIFont) { + button.titleLabel!.font = font + #if targetEnvironment(macCatalyst) + label.font = font + #endif + } + + private func update() { + button.isEnabled = isEnabled + if isEnabled { + #if targetEnvironment(macCatalyst) + label.isHidden = true + button.isHidden = false + #endif + button.setTitle("Vote", for: .normal) + } else { + #if targetEnvironment(macCatalyst) + label.text = disabledTitle + label.isHidden = false + button.isHidden = true + #else + button.setTitle(disabledTitle, for: .disabled) + #endif + } + } + +} diff --git a/Tusker/Views/Poll/StatusPollView.swift b/Tusker/Views/Poll/StatusPollView.swift index 04c49d2d..c991e35a 100644 --- a/Tusker/Views/Poll/StatusPollView.swift +++ b/Tusker/Views/Poll/StatusPollView.swift @@ -26,7 +26,7 @@ class StatusPollView: UIView { private(set) var poll: Poll? private var optionsView: PollOptionsView! - private var voteButton: UIButton! + private var voteButton: PollVoteButton! private var infoLabel: UILabel! private var canVote = true @@ -54,12 +54,16 @@ class StatusPollView: UIView { infoLabel.adjustsFontSizeToFitWidth = true addSubview(infoLabel) - voteButton = UIButton(type: .system) +// voteButton = UIButton(type: .system) +// voteButton.translatesAutoresizingMaskIntoConstraints = false +// voteButton.addTarget(self, action: #selector(votePressed), for: .touchUpInside) +// voteButton.setTitle("Vote", for: .normal) +// voteButton.setTitleColor(.secondaryLabel, for: .disabled) +// voteButton.titleLabel!.font = infoLabel.font + voteButton = PollVoteButton() voteButton.translatesAutoresizingMaskIntoConstraints = false - voteButton.addTarget(self, action: #selector(votePressed), for: .touchUpInside) - voteButton.setTitle("Vote", for: .normal) - voteButton.setTitleColor(.secondaryLabel, for: .disabled) - voteButton.titleLabel!.font = infoLabel.font + voteButton.addTarget(self, action: #selector(votePressed)) + voteButton.setFont(infoLabel.font) addSubview(voteButton) NSLayoutConstraint.activate([ @@ -117,17 +121,17 @@ class StatusPollView: UIView { } if expired { - voteButton.setTitle("Expired", for: .disabled) + voteButton.disabledTitle = "Expired" } else if poll.voted ?? false { if status.account.id == mastodonController.account.id { - voteButton.setTitle("", for: .disabled) + voteButton.isHidden = true } else { - voteButton.setTitle("Voted", for: .disabled) + voteButton.disabledTitle = "Voted" } } else if poll.multiple { - voteButton.setTitle("Select multiple", for: .disabled) + voteButton.disabledTitle = "Select multiple" } else { - voteButton.setTitle("Select one", for: .disabled) + voteButton.disabledTitle = "Select one" } voteButton.isEnabled = false } @@ -139,7 +143,7 @@ class StatusPollView: UIView { @objc private func votePressed() { optionsView.isEnabled = false voteButton.isEnabled = false - voteButton.setTitle("Voted", for: .disabled) + voteButton.disabledTitle = "Voted" UIImpactFeedbackGenerator(style: .medium).impactOccurred()