Move MenuPicker to separate package

This commit is contained in:
Shadowfacts 2023-03-07 10:07:45 -05:00
parent 391ea1b46a
commit 850a0e90ce
9 changed files with 76 additions and 18 deletions

9
Packages/TuskerComponents/.gitignore vendored Normal file
View File

@ -0,0 +1,9 @@
.DS_Store
/.build
/Packages
/*.xcodeproj
xcuserdata/
DerivedData/
.swiftpm/config/registries.json
.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata
.netrc

View File

@ -0,0 +1,31 @@
// swift-tools-version: 5.7
// The swift-tools-version declares the minimum version of Swift required to build this package.
import PackageDescription
let package = Package(
name: "TuskerComponents",
platforms: [
.iOS(.v15),
],
products: [
// Products define the executables and libraries a package produces, and make them visible to other packages.
.library(
name: "TuskerComponents",
targets: ["TuskerComponents"]),
],
dependencies: [
// Dependencies declare other packages that this package depends on.
// .package(url: /* package url */, from: "1.0.0"),
],
targets: [
// Targets are the basic building blocks of a package. A target can define a module or a test suite.
// Targets can depend on other targets in this package, and on products in packages this package depends on.
.target(
name: "TuskerComponents",
dependencies: []),
.testTarget(
name: "TuskerComponentsTests",
dependencies: ["TuskerComponents"]),
]
)

View File

@ -0,0 +1,3 @@
# TuskerComponents
A description of this package.

View File

@ -1,6 +1,6 @@
// //
// MenuPicker.swift // MenuPicker.swift
// Tusker // TuskerComponents
// //
// Created by Shadowfacts on 11/7/22. // Created by Shadowfacts on 11/7/22.
// Copyright © 2022 Shadowfacts. All rights reserved. // Copyright © 2022 Shadowfacts. All rights reserved.
@ -8,25 +8,31 @@
import SwiftUI import SwiftUI
struct MenuPicker<Value: Hashable>: UIViewRepresentable { public struct MenuPicker<Value: Hashable>: UIViewRepresentable {
typealias UIViewType = UIButton public typealias UIViewType = UIButton
@Binding var selection: Value @Binding var selection: Value
let options: [Option] let options: [Option]
var buttonStyle: ButtonStyle = .labelAndIcon var buttonStyle: ButtonStyle
private var selectedOption: Option { private var selectedOption: Option {
options.first(where: { $0.value == selection })! options.first(where: { $0.value == selection })!
} }
func makeUIView(context: Context) -> UIButton { public init(selection: Binding<Value>, options: [Option], buttonStyle: ButtonStyle = .labelAndIcon) {
self._selection = selection
self.options = options
self.buttonStyle = buttonStyle
}
public func makeUIView(context: Context) -> UIButton {
let button = UIButton() let button = UIButton()
button.showsMenuAsPrimaryAction = true button.showsMenuAsPrimaryAction = true
button.setContentHuggingPriority(.required, for: .horizontal) button.setContentHuggingPriority(.required, for: .horizontal)
return button return button
} }
func updateUIView(_ button: UIButton, context: Context) { public func updateUIView(_ button: UIButton, context: Context) {
var config = UIButton.Configuration.borderless() var config = UIButton.Configuration.borderless()
if #available(iOS 16.0, *) { if #available(iOS 16.0, *) {
config.indicator = .popup config.indicator = .popup
@ -49,14 +55,14 @@ struct MenuPicker<Value: Hashable>: UIViewRepresentable {
button.isPointerInteractionEnabled = buttonStyle == .iconOnly button.isPointerInteractionEnabled = buttonStyle == .iconOnly
} }
struct Option { public struct Option {
let value: Value public let value: Value
let title: String public let title: String
let subtitle: String? public let subtitle: String?
let image: UIImage? public let image: UIImage?
let accessibilityLabel: String? public let accessibilityLabel: String?
init(value: Value, title: String, subtitle: String? = nil, image: UIImage? = nil, accessibilityLabel: String? = nil) { public init(value: Value, title: String, subtitle: String? = nil, image: UIImage? = nil, accessibilityLabel: String? = nil) {
self.value = value self.value = value
self.title = title self.title = title
self.subtitle = subtitle self.subtitle = subtitle
@ -65,7 +71,7 @@ struct MenuPicker<Value: Hashable>: UIViewRepresentable {
} }
} }
enum ButtonStyle { public enum ButtonStyle {
case labelAndIcon, labelOnly, iconOnly case labelAndIcon, labelOnly, iconOnly
var hasLabel: Bool { var hasLabel: Bool {

View File

@ -117,6 +117,7 @@
D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.swift */; }; D6311C5025B3765B00B27539 /* ImageDataCache.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6311C4F25B3765B00B27539 /* ImageDataCache.swift */; };
D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; }; D6333B372137838300CE884A /* AttributedString+Helpers.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B362137838300CE884A /* AttributedString+Helpers.swift */; };
D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; }; D6333B792139AEFD00CE884A /* Date+TimeAgo.swift in Sources */ = {isa = PBXBuildFile; fileRef = D6333B782139AEFD00CE884A /* Date+TimeAgo.swift */; };
D635237129B78A7D009ED5E7 /* TuskerComponents in Frameworks */ = {isa = PBXBuildFile; productRef = D635237029B78A7D009ED5E7 /* TuskerComponents */; };
D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */; }; D63661C02381C144004B9E16 /* PreferencesNavigationController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D63661BF2381C144004B9E16 /* PreferencesNavigationController.swift */; };
D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */; }; D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = D6370B9A24421FF30092A7FF /* Tusker.xcdatamodeld */; };
D63CC702290EC0B8000E19DE /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = D63CC701290EC0B8000E19DE /* Sentry */; }; D63CC702290EC0B8000E19DE /* Sentry in Frameworks */ = {isa = PBXBuildFile; productRef = D63CC701290EC0B8000E19DE /* Sentry */; };
@ -180,7 +181,6 @@
D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */; }; D667E5F82135C3040057A976 /* Mastodon+Equatable.swift in Sources */ = {isa = PBXBuildFile; fileRef = D667E5F72135C3040057A976 /* Mastodon+Equatable.swift */; };
D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */; }; D66A77BB233838DC0058F1EC /* UIFont+Traits.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */; };
D66C900B28DAB7FD00217BF2 /* TimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66C900A28DAB7FD00217BF2 /* TimelineViewController.swift */; }; D66C900B28DAB7FD00217BF2 /* TimelineViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = D66C900A28DAB7FD00217BF2 /* TimelineViewController.swift */; };
D673ACCE2919E74200D6F8B0 /* MenuPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = D673ACCD2919E74200D6F8B0 /* MenuPicker.swift */; };
D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D674A50827F9128D00BA03AC /* Pachyderm */; }; D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */ = {isa = PBXBuildFile; productRef = D674A50827F9128D00BA03AC /* Pachyderm */; };
D677284824ECBCB100C732D3 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D677284724ECBCB100C732D3 /* ComposeView.swift */; }; D677284824ECBCB100C732D3 /* ComposeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D677284724ECBCB100C732D3 /* ComposeView.swift */; };
D677284A24ECBDF400C732D3 /* ComposeCurrentAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = D677284924ECBDF400C732D3 /* ComposeCurrentAccount.swift */; }; D677284A24ECBDF400C732D3 /* ComposeCurrentAccount.swift in Sources */ = {isa = PBXBuildFile; fileRef = D677284924ECBDF400C732D3 /* ComposeCurrentAccount.swift */; };
@ -599,7 +599,6 @@
D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = "<group>"; }; D66A77BA233838DC0058F1EC /* UIFont+Traits.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIFont+Traits.swift"; sourceTree = "<group>"; };
D66C900A28DAB7FD00217BF2 /* TimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewController.swift; sourceTree = "<group>"; }; D66C900A28DAB7FD00217BF2 /* TimelineViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelineViewController.swift; sourceTree = "<group>"; };
D671A6BE299DA96100A81FEA /* Tusker-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tusker-Bridging-Header.h"; sourceTree = "<group>"; }; D671A6BE299DA96100A81FEA /* Tusker-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Tusker-Bridging-Header.h"; sourceTree = "<group>"; };
D673ACCD2919E74200D6F8B0 /* MenuPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MenuPicker.swift; sourceTree = "<group>"; };
D674A50727F910F300BA03AC /* Pachyderm */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Pachyderm; path = Packages/Pachyderm; sourceTree = "<group>"; }; D674A50727F910F300BA03AC /* Pachyderm */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Pachyderm; path = Packages/Pachyderm; sourceTree = "<group>"; };
D677284724ECBCB100C732D3 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = "<group>"; }; D677284724ECBCB100C732D3 /* ComposeView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeView.swift; sourceTree = "<group>"; };
D677284924ECBDF400C732D3 /* ComposeCurrentAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeCurrentAccount.swift; sourceTree = "<group>"; }; D677284924ECBDF400C732D3 /* ComposeCurrentAccount.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeCurrentAccount.swift; sourceTree = "<group>"; };
@ -710,6 +709,7 @@
D6BC9DB4232D4CE3002CA326 /* NotificationsMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsMode.swift; sourceTree = "<group>"; }; D6BC9DB4232D4CE3002CA326 /* NotificationsMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotificationsMode.swift; sourceTree = "<group>"; };
D6BC9DD6232D7811002CA326 /* TimelinesPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesPageViewController.swift; sourceTree = "<group>"; }; D6BC9DD6232D7811002CA326 /* TimelinesPageViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = TimelinesPageViewController.swift; sourceTree = "<group>"; };
D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsViewController.swift; sourceTree = "<group>"; }; D6BC9DD9232D8BE5002CA326 /* SearchResultsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SearchResultsViewController.swift; sourceTree = "<group>"; };
D6BD395C29B789D5005FFD2B /* TuskerComponents */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = TuskerComponents; path = Packages/TuskerComponents; sourceTree = "<group>"; };
D6BEA243291A0C83002F4D01 /* Duckable */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Duckable; path = Packages/Duckable; sourceTree = "<group>"; }; D6BEA243291A0C83002F4D01 /* Duckable */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = Duckable; path = Packages/Duckable; sourceTree = "<group>"; };
D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Duckable+Root.swift"; sourceTree = "<group>"; }; D6BEA246291A0F2D002F4D01 /* Duckable+Root.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Duckable+Root.swift"; sourceTree = "<group>"; };
D6BEA248291C6118002F4D01 /* DraftsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsView.swift; sourceTree = "<group>"; }; D6BEA248291C6118002F4D01 /* DraftsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DraftsView.swift; sourceTree = "<group>"; };
@ -812,6 +812,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D6FA94E129B52898006AAC51 /* InstanceFeatures in Frameworks */, D6FA94E129B52898006AAC51 /* InstanceFeatures in Frameworks */,
D635237129B78A7D009ED5E7 /* TuskerComponents in Frameworks */,
D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */, D674A50927F9128D00BA03AC /* Pachyderm in Frameworks */,
D659F35E2953A212002D944A /* TTTKit in Frameworks */, D659F35E2953A212002D944A /* TTTKit in Frameworks */,
D6B0026E29B5248800C70BE2 /* UserAccounts in Frameworks */, D6B0026E29B5248800C70BE2 /* UserAccounts in Frameworks */,
@ -1466,7 +1467,6 @@
D620483323D3801D008A63EF /* LinkTextView.swift */, D620483323D3801D008A63EF /* LinkTextView.swift */,
D61A45E728DF477D002BE511 /* LoadingCollectionViewCell.swift */, D61A45E728DF477D002BE511 /* LoadingCollectionViewCell.swift */,
D6262C9928D01C4B00390C1F /* LoadingTableViewCell.swift */, D6262C9928D01C4B00390C1F /* LoadingTableViewCell.swift */,
D673ACCD2919E74200D6F8B0 /* MenuPicker.swift */,
D68E6F58253C9969001A1B4C /* MultiSourceEmojiLabel.swift */, D68E6F58253C9969001A1B4C /* MultiSourceEmojiLabel.swift */,
D627943A23A55BA600D38C68 /* NavigableTableViewCell.swift */, D627943A23A55BA600D38C68 /* NavigableTableViewCell.swift */,
D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */, D6D7069F29466649000827ED /* ScrollingSegmentedControl.swift */,
@ -1541,6 +1541,7 @@
D68A76F22953915C001DA1B3 /* TTTKit */, D68A76F22953915C001DA1B3 /* TTTKit */,
D6B0026C29B5245400C70BE2 /* UserAccounts */, D6B0026C29B5245400C70BE2 /* UserAccounts */,
D6FA94DF29B52891006AAC51 /* InstanceFeatures */, D6FA94DF29B52891006AAC51 /* InstanceFeatures */,
D6BD395C29B789D5005FFD2B /* TuskerComponents */,
D6D4DDCE212518A000E1C4BB /* Tusker */, D6D4DDCE212518A000E1C4BB /* Tusker */,
D6D4DDE3212518A200E1C4BB /* TuskerTests */, D6D4DDE3212518A200E1C4BB /* TuskerTests */,
D6D4DDEE212518A200E1C4BB /* TuskerUITests */, D6D4DDEE212518A200E1C4BB /* TuskerUITests */,
@ -1745,6 +1746,7 @@
D659F35D2953A212002D944A /* TTTKit */, D659F35D2953A212002D944A /* TTTKit */,
D6B0026D29B5248800C70BE2 /* UserAccounts */, D6B0026D29B5248800C70BE2 /* UserAccounts */,
D6FA94E029B52898006AAC51 /* InstanceFeatures */, D6FA94E029B52898006AAC51 /* InstanceFeatures */,
D635237029B78A7D009ED5E7 /* TuskerComponents */,
); );
productName = Tusker; productName = Tusker;
productReference = D6D4DDCC212518A000E1C4BB /* Tusker.app */; productReference = D6D4DDCC212518A000E1C4BB /* Tusker.app */;
@ -2081,7 +2083,6 @@
D6BEA249291C6118002F4D01 /* DraftsView.swift in Sources */, D6BEA249291C6118002F4D01 /* DraftsView.swift in Sources */,
D61F75AD293AF39000C0B37F /* Filter+Helpers.swift in Sources */, D61F75AD293AF39000C0B37F /* Filter+Helpers.swift in Sources */,
D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */, D6531DEE246B81C9000F9538 /* GifvAttachmentView.swift in Sources */,
D673ACCE2919E74200D6F8B0 /* MenuPicker.swift in Sources */,
D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */, D6370B9C24421FF30092A7FF /* Tusker.xcdatamodeld in Sources */,
D601FA83297EEC3F00A8E8B5 /* SuggestedProfileCardCollectionViewCell.swift in Sources */, D601FA83297EEC3F00A8E8B5 /* SuggestedProfileCardCollectionViewCell.swift in Sources */,
D691772E29AA5D420054D7EF /* UserActivityHandlingContext.swift in Sources */, D691772E29AA5D420054D7EF /* UserActivityHandlingContext.swift in Sources */,
@ -2945,6 +2946,10 @@
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
productName = Pachyderm; productName = Pachyderm;
}; };
D635237029B78A7D009ED5E7 /* TuskerComponents */ = {
isa = XCSwiftPackageProductDependency;
productName = TuskerComponents;
};
D63CC701290EC0B8000E19DE /* Sentry */ = { D63CC701290EC0B8000E19DE /* Sentry */ = {
isa = XCSwiftPackageProductDependency; isa = XCSwiftPackageProductDependency;
package = D63CC700290EC0B8000E19DE /* XCRemoteSwiftPackageReference "sentry-cocoa" */; package = D63CC700290EC0B8000E19DE /* XCRemoteSwiftPackageReference "sentry-cocoa" */;

View File

@ -7,6 +7,7 @@
// //
import SwiftUI import SwiftUI
import TuskerComponents
struct ComposePollView: View { struct ComposePollView: View {
private static let formatter: DateComponentsFormatter = { private static let formatter: DateComponentsFormatter = {

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import Pachyderm import Pachyderm
import TuskerComponents
struct ComposeToolbar: View { struct ComposeToolbar: View {
static let height: CGFloat = 44 static let height: CGFloat = 44

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import Pachyderm import Pachyderm
import TuskerComponents
struct EditFilterView: View { struct EditFilterView: View {
private static let expiresInOptions: [MenuPicker<TimeInterval>.Option] = { private static let expiresInOptions: [MenuPicker<TimeInterval>.Option] = {

View File

@ -8,6 +8,7 @@
import SwiftUI import SwiftUI
import Pachyderm import Pachyderm
import TuskerComponents
struct MuteAccountView: View { struct MuteAccountView: View {
private static let durationOptions: [MenuPicker<TimeInterval>.Option] = { private static let durationOptions: [MenuPicker<TimeInterval>.Option] = {