Adds “Contributors” section to Credits

Lists everyone who has contributed to Delta in some way besides the core team, as well as what they contributed.

Moves Grant Gliner and Chris Rittenhouse to Contributors from main Credits.
This commit is contained in:
Riley Testut 2023-02-06 14:35:43 -06:00
parent d1c45c9ad0
commit 45665138b2
6 changed files with 389 additions and 4 deletions

View File

@ -170,11 +170,14 @@
D524F4A3273DE9C000D500B2 /* ProcessInfo+JIT.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */; }; D524F4A3273DE9C000D500B2 /* ProcessInfo+JIT.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */; };
D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */; }; D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */ = {isa = PBXBuildFile; fileRef = D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */; };
D5011C48281B6E8B00A0760B /* CharacterSet+Filename.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */; }; D5011C48281B6E8B00A0760B /* CharacterSet+Filename.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */; };
D53415A5298C782A00FD67B1 /* ContributorsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D53415A4298C782A00FD67B1 /* ContributorsView.swift */; };
D53415A7298C78BC00FD67B1 /* Contributors.plist in Resources */ = {isa = PBXBuildFile; fileRef = D53415A6298C78BC00FD67B1 /* Contributors.plist */; };
D5864970297734280081477E /* CheatMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586496F297734280081477E /* CheatMetadata.swift */; }; D5864970297734280081477E /* CheatMetadata.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586496F297734280081477E /* CheatMetadata.swift */; };
D586497229774ABD0081477E /* CheatBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586497129774ABD0081477E /* CheatBase.swift */; }; D586497229774ABD0081477E /* CheatBase.swift in Sources */ = {isa = PBXBuildFile; fileRef = D586497129774ABD0081477E /* CheatBase.swift */; };
D5864978297756CE0081477E /* CheatBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5864977297756CE0081477E /* CheatBaseView.swift */; }; D5864978297756CE0081477E /* CheatBaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5864977297756CE0081477E /* CheatBaseView.swift */; };
D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */; }; D5A98CE2284EF14B00E023E5 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */; };
D5AAF27729884F8600F21ACF /* CheatDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AAF27629884F8600F21ACF /* CheatDevice.swift */; }; D5AAF27729884F8600F21ACF /* CheatDevice.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5AAF27629884F8600F21ACF /* CheatDevice.swift */; };
D5D797E6298D946200738869 /* Contributor.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5D797E5298D946200738869 /* Contributor.swift */; };
D5F82FB82981D3AC00B229AF /* LegacySearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */; }; D5F82FB82981D3AC00B229AF /* LegacySearchBar.swift in Sources */ = {isa = PBXBuildFile; fileRef = D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */
@ -373,11 +376,14 @@
D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+JIT.swift"; sourceTree = "<group>"; }; D524F4A2273DE9C000D500B2 /* ProcessInfo+JIT.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ProcessInfo+JIT.swift"; sourceTree = "<group>"; };
D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ServerManager+Delta.swift"; sourceTree = "<group>"; }; D524F4A4273DEBB400D500B2 /* ServerManager+Delta.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "ServerManager+Delta.swift"; sourceTree = "<group>"; };
D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Filename.swift"; sourceTree = "<group>"; }; D5011C47281B6E8B00A0760B /* CharacterSet+Filename.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "CharacterSet+Filename.swift"; sourceTree = "<group>"; };
D53415A4298C782A00FD67B1 /* ContributorsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContributorsView.swift; sourceTree = "<group>"; };
D53415A6298C78BC00FD67B1 /* Contributors.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Contributors.plist; sourceTree = "<group>"; };
D586496F297734280081477E /* CheatMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatMetadata.swift; sourceTree = "<group>"; }; D586496F297734280081477E /* CheatMetadata.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatMetadata.swift; sourceTree = "<group>"; };
D586497129774ABD0081477E /* CheatBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatBase.swift; sourceTree = "<group>"; }; D586497129774ABD0081477E /* CheatBase.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatBase.swift; sourceTree = "<group>"; };
D5864977297756CE0081477E /* CheatBaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatBaseView.swift; sourceTree = "<group>"; }; D5864977297756CE0081477E /* CheatBaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatBaseView.swift; sourceTree = "<group>"; };
D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; }; D5A98CE1284EF14B00E023E5 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
D5AAF27629884F8600F21ACF /* CheatDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatDevice.swift; sourceTree = "<group>"; }; D5AAF27629884F8600F21ACF /* CheatDevice.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CheatDevice.swift; sourceTree = "<group>"; };
D5D797E5298D946200738869 /* Contributor.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Contributor.swift; sourceTree = "<group>"; };
D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySearchBar.swift; sourceTree = "<group>"; }; D5F82FB72981D3AC00B229AF /* LegacySearchBar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LegacySearchBar.swift; sourceTree = "<group>"; };
DC866E433B3BA9AE18ABA1EC /* libPods-Delta.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Delta.a"; sourceTree = BUILT_PRODUCTS_DIR; }; DC866E433B3BA9AE18ABA1EC /* libPods-Delta.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-Delta.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */ /* End PBXFileReference section */
@ -744,6 +750,7 @@
BF11734E1DA32CEC00047DF8 /* Controllers */, BF11734E1DA32CEC00047DF8 /* Controllers */,
BF1DAD5B1D9F574900E752A7 /* Controller Skins */, BF1DAD5B1D9F574900E752A7 /* Controller Skins */,
BF48F74C219A16C100BC2FC1 /* Syncing */, BF48F74C219A16C100BC2FC1 /* Syncing */,
D5D797E4298D944C00738869 /* Contributors */,
); );
path = Settings; path = Settings;
sourceTree = "<group>"; sourceTree = "<group>";
@ -795,6 +802,7 @@
BF6BB2451BB73FE800CCF94A /* Assets.xcassets */, BF6BB2451BB73FE800CCF94A /* Assets.xcassets */,
BF02D5D91DDEBB3000A5E131 /* openvgdb.sqlite */, BF02D5D91DDEBB3000A5E131 /* openvgdb.sqlite */,
D5050A1B2989A84200ABE08D /* cheatbase.sqlite */, D5050A1B2989A84200ABE08D /* cheatbase.sqlite */,
D53415A6298C78BC00FD67B1 /* Contributors.plist */,
); );
path = Resources; path = Resources;
sourceTree = "<group>"; sourceTree = "<group>";
@ -917,6 +925,15 @@
path = Cheats; path = Cheats;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
D5D797E4298D944C00738869 /* Contributors */ = {
isa = PBXGroup;
children = (
D5D797E5298D946200738869 /* Contributor.swift */,
D53415A4298C782A00FD67B1 /* ContributorsView.swift */,
);
path = Contributors;
sourceTree = "<group>";
};
FD1E8AE87FA2DB8793F7B937 /* Pods */ = { FD1E8AE87FA2DB8793F7B937 /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
@ -1023,6 +1040,7 @@
BF3540001C5DA3C500C1184C /* PausePresentationControllerContentView.xib in Resources */, BF3540001C5DA3C500C1184C /* PausePresentationControllerContentView.xib in Resources */,
BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */, BF5E7F461B9A652600AE44F8 /* Settings.storyboard in Resources */,
BF02D5DA1DDEBB3000A5E131 /* openvgdb.sqlite in Resources */, BF02D5DA1DDEBB3000A5E131 /* openvgdb.sqlite in Resources */,
D53415A7298C78BC00FD67B1 /* Contributors.plist in Resources */,
BF71CF8A1FE904B1001F1613 /* GameTableViewCell.xib in Resources */, BF71CF8A1FE904B1001F1613 /* GameTableViewCell.xib in Resources */,
BFFC46461D59861000AF2CC6 /* LaunchScreen.storyboard in Resources */, BFFC46461D59861000AF2CC6 /* LaunchScreen.storyboard in Resources */,
D5050A1C2989A84200ABE08D /* cheatbase.sqlite in Resources */, D5050A1C2989A84200ABE08D /* cheatbase.sqlite in Resources */,
@ -1183,6 +1201,7 @@
BF5942951E09BD1A0051894B /* NSManagedObjectContext+Conveniences.swift in Sources */, BF5942951E09BD1A0051894B /* NSManagedObjectContext+Conveniences.swift in Sources */,
BFC3628021ADE2BA00EF2BE6 /* UIAlertController+Error.swift in Sources */, BFC3628021ADE2BA00EF2BE6 /* UIAlertController+Error.swift in Sources */,
BF353FF91C5D870B00C1184C /* MenuItem.swift in Sources */, BF353FF91C5D870B00C1184C /* MenuItem.swift in Sources */,
D5D797E6298D946200738869 /* Contributor.swift in Sources */,
BFDB3418219E4B1700595A62 /* SyncStatusViewController.swift in Sources */, BFDB3418219E4B1700595A62 /* SyncStatusViewController.swift in Sources */,
BF18B61F1E2985F900F70067 /* UIAlertController+Importing.swift in Sources */, BF18B61F1E2985F900F70067 /* UIAlertController+Importing.swift in Sources */,
D586497229774ABD0081477E /* CheatBase.swift in Sources */, D586497229774ABD0081477E /* CheatBase.swift in Sources */,
@ -1193,6 +1212,7 @@
BF59426B1E09BBD00051894B /* GridCollectionViewLayout.swift in Sources */, BF59426B1E09BBD00051894B /* GridCollectionViewLayout.swift in Sources */,
BF6424851F5CBDC900D6AB44 /* UIView+ParentViewController.swift in Sources */, BF6424851F5CBDC900D6AB44 /* UIView+ParentViewController.swift in Sources */,
BF04E6FF1DB8625C000F35D3 /* ControllerSkinsViewController.swift in Sources */, BF04E6FF1DB8625C000F35D3 /* ControllerSkinsViewController.swift in Sources */,
D53415A5298C782A00FD67B1 /* ContributorsView.swift in Sources */,
BF5942891E09BC8B0051894B /* _GameCollection.swift in Sources */, BF5942891E09BC8B0051894B /* _GameCollection.swift in Sources */,
BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */, BF34FA111CF1899D006624C7 /* CheatTextView.swift in Sources */,
D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */, D524F4A5273DEBB400D500B2 /* ServerManager+Delta.swift in Sources */,

View File

@ -643,6 +643,22 @@
</subviews> </subviews>
</tableViewCellContentView> </tableViewCellContentView>
</tableViewCell> </tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="DetailCell" textLabel="g59-8E-zW7" style="IBUITableViewCellStyleDefault" id="hkv-lx-68h">
<rect key="frame" x="0.0" y="1766.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="hkv-lx-68h" id="bNT-kB-3cI">
<rect key="frame" x="0.0" y="0.0" width="348.5" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" ambiguous="YES" text="Contributors" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="g59-8E-zW7">
<rect key="frame" x="16" y="0.0" width="324.5" height="44"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="DetailCell" textLabel="2K3-IL-94S" style="IBUITableViewCellStyleDefault" id="j7p-ZK-mHq"> <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="DetailCell" textLabel="2K3-IL-94S" style="IBUITableViewCellStyleDefault" id="j7p-ZK-mHq">
<rect key="frame" x="0.0" y="1567.5" width="375" height="44"/> <rect key="frame" x="0.0" y="1567.5" width="375" height="44"/>
<autoresizingMask key="autoresizingMask"/> <autoresizingMask key="autoresizingMask"/>

View File

@ -0,0 +1,45 @@
//
// Contributor.swift
// Delta
//
// Created by Riley Testut on 2/3/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import Foundation
struct Contributor: Identifiable, Decodable
{
var name: String
var id: String {
// Use names as identifiers for now.
return self.name
}
var url: URL? {
guard let link = self.link, let url = URL(string: link) else { return nil }
return url
}
private var link: String?
var linkName: String?
var contributions: [Contribution]
}
struct Contribution: Identifiable, Decodable
{
var name: String
var id: String {
// Use names as identifiers for now.
return self.name
}
var url: URL? {
guard let link = self.link, let url = URL(string: link) else { return nil }
return url
}
private var link: String?
}

View File

@ -0,0 +1,200 @@
//
// ContributionsView.swift
// Delta
//
// Created by Riley Testut on 2/2/23.
// Copyright © 2023 Riley Testut. All rights reserved.
//
import SwiftUI
import SafariServices
@available(iOS 14, *)
private extension NavigationLink where Label == EmptyView, Destination == EmptyView
{
// Copied from https://stackoverflow.com/a/66891173
static var empty: NavigationLink {
self.init(destination: EmptyView(), label: { EmptyView() })
}
}
@available(iOS 14, *)
extension ContributorsView
{
fileprivate class ViewModel: ObservableObject
{
@Published
var contributors: [Contributor]?
@Published
var error: Error?
@Published
var webViewURL: URL?
weak var hostingController: UIViewController?
func loadContributors()
{
guard self.contributors == nil else { return }
do
{
let fileURL = Bundle.main.url(forResource: "Contributors", withExtension: "plist")!
let data = try Data(contentsOf: fileURL)
let contributors = try PropertyListDecoder().decode([Contributor].self, from: data)
self.contributors = contributors
}
catch
{
self.error = error
}
}
}
static func makeViewController() -> UIHostingController<some View>
{
let viewModel = ViewModel()
let contributorsView = ContributorsView(viewModel: viewModel)
let hostingController = UIHostingController(rootView: contributorsView)
hostingController.title = NSLocalizedString("Contributors", comment: "")
viewModel.hostingController = hostingController
return hostingController
}
}
@available(iOS 14, *)
struct ContributorsView: View
{
@StateObject
private var viewModel: ViewModel
@State
private var showErrorAlert: Bool = false
var body: some View {
List {
Section(content: {}, footer: {
Text("These individuals have contributed to the open-source Delta project on GitHub.\n\nThank you to all our contributors, your help is much appreciated 💜")
.font(.subheadline)
})
ForEach(viewModel.contributors ?? []) { contributor in
Section {
// First row = contributor
ContributionCell(name: Text(contributor.name).bold(), url: contributor.url, linkName: contributor.linkName) { webViewURL in
viewModel.webViewURL = webViewURL
}
// Remaining rows = contributions
ForEach(contributor.contributions) { contribution in
ContributionCell(name: Text(contribution.name), url: contribution.url) { webViewURL in
viewModel.webViewURL = webViewURL
}
}
}
}
}
.listStyle(.grouped) // TODO: Change to .insetGrouped once we drop iOS 13 support.
.environmentObject(viewModel)
.alert(isPresented: $showErrorAlert) {
Alert(title: Text("Unable to Load Contributors"), message: Text(viewModel.error?.localizedDescription ?? ""), dismissButton: .default(Text("OK")) {
guard let hostingController = viewModel.hostingController else { return }
hostingController.navigationController?.popViewController(animated: true)
})
}
.onReceive(viewModel.$error) { error in
guard error != nil else { return }
showErrorAlert = true
}
.onReceive(viewModel.$webViewURL) { webViewURL in
guard let webViewURL else { return }
openURL(webViewURL)
}
.onAppear {
viewModel.loadContributors()
}
}
fileprivate init(contributors: [Contributor]? = nil, viewModel: ViewModel = ViewModel())
{
if let contributors
{
// Don't overwrite passed-in viewModel.contributors if contributors is nil.
viewModel.contributors = contributors
}
self._viewModel = StateObject(wrappedValue: viewModel)
}
}
@available(iOS 14, *)
struct ContributionCell: View
{
var name: Text
var url: URL?
var linkName: String?
var action: (URL) -> Void
var body: some View {
let body = Button {
guard let url else { return }
Task { @MainActor in
// Dispatch Task to avoid "Publishing changes from within view updates is not allowed, this will cause undefined behavior." runtime error on iOS 16.
self.action(url)
}
} label: {
HStack {
self.name
.font(.system(size: 17)) // Match Settings screen
Spacer()
if let linkName
{
Text(linkName)
.font(.system(size: 17)) // Match Settings screen
.foregroundColor(.gray)
}
if url != nil
{
NavigationLink.empty
.fixedSize()
}
}
}
.accentColor(.primary)
if url != nil
{
body
}
else
{
// No URL to open, so disable cell highlighting.
body.buttonStyle(.plain)
}
}
}
@available(iOS 14, *)
private extension ContributorsView
{
func openURL(_ url: URL)
{
guard let hostingController = viewModel.hostingController else { return }
let safariViewController = SFSafariViewController(url: url)
safariViewController.preferredControlTintColor = .deltaPurple
hostingController.present(safariViewController, animated: true)
}
}

View File

@ -49,6 +49,7 @@ private extension SettingsViewController
case caroline case caroline
case grant case grant
case litRitt case litRitt
case contributors
case softwareLicenses case softwareLicenses
} }
} }
@ -279,6 +280,13 @@ private extension SettingsViewController
} }
} }
} }
@available(iOS 14, *)
func showContributors()
{
let hostingController = ContributorsView.makeViewController()
self.navigationController?.pushViewController(hostingController, animated: true)
}
} }
private extension SettingsViewController private extension SettingsViewController
@ -418,6 +426,10 @@ extension SettingsViewController
case .caroline: self.openTwitter(username: "1carolinemoore") case .caroline: self.openTwitter(username: "1carolinemoore")
case .grant: self.openTwitter(username: "grantgliner") case .grant: self.openTwitter(username: "grantgliner")
case .litRitt: self.openTwitter(username: "litritt_z") case .litRitt: self.openTwitter(username: "litritt_z")
case .contributors:
guard #available(iOS 14, *) else { return }
self.showContributors()
case .softwareLicenses: break case .softwareLicenses: break
} }
} }
@ -425,13 +437,35 @@ extension SettingsViewController
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{ {
primary:
switch Section(rawValue: indexPath.section)! switch Section(rawValue: indexPath.section)!
{ {
#if !BETA case .credits:
case .credits where indexPath.row == CreditsRow.litRitt.rawValue: return 0.0 let row = CreditsRow(rawValue: indexPath.row)!
#endif switch row
default: return super.tableView(tableView, heightForRowAt: indexPath) {
case .grant:
// Hide row on iOS 14 and above
guard #available(iOS 14, *) else { break primary }
return 0.0
case .litRitt:
// Hide row on iOS 14 and above
guard #available(iOS 14, *) else { break primary }
return 0.0
case .contributors:
// Hide row on iOS 13 and below
guard #unavailable(iOS 14) else { break primary }
return 0.0
default: break
}
default: break
} }
return super.tableView(tableView, heightForRowAt: indexPath)
} }
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String?

View File

@ -0,0 +1,70 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>name</key>
<string>Grant Gliner</string>
<key>link</key>
<string>https://twitter.com/GrantGliner</string>
<key>linkName</key>
<string>@GrantGliner</string>
<key>contributions</key>
<array>
<dict>
<key>name</key>
<string>Pause Menu Icons</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>Eric Lewis</string>
<key>link</key>
<string>https://github.com/ericlewis</string>
<key>linkName</key>
<string>github.com/ericlewis</string>
<key>contributions</key>
<array>
<dict>
<key>name</key>
<string>Dark Mode</string>
<key>link</key>
<string>https://github.com/rileytestut/Delta/pull/82</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>Chris Rittenhouse</string>
<key>link</key>
<string>https://github.com/LitRitt</string>
<key>linkName</key>
<string>github.com/LitRitt</string>
<key>contributions</key>
<array>
<dict>
<key>name</key>
<string>Genesis Skin</string>
</dict>
</array>
</dict>
<dict>
<key>name</key>
<string>Noah Keck</string>
<key>link</key>
<string>https://github.com/noah978</string>
<key>linkName</key>
<string>github.com/noah978</string>
<key>contributions</key>
<array>
<dict>
<key>name</key>
<string>CheatBase</string>
<key>link</key>
<string>https://github.com/CheatBase/CheatBase</string>
</dict>
</array>
</dict>
</array>
</plist>