Skip to content

Commit

Permalink
feat: sponsors in credits, reorganizations
Browse files Browse the repository at this point in the history
  • Loading branch information
khcrysalis committed Oct 29, 2024
1 parent 0914572 commit e1fb7ce
Show file tree
Hide file tree
Showing 11 changed files with 346 additions and 209 deletions.
12 changes: 12 additions & 0 deletions Shared/Data/CoreData/Download/Sources.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,4 +51,16 @@ class SourceGET {
return .failure(error)
}
}

func parsec(data: Data) -> Result<[CreditsPerson], Error> {
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .iso8601
let source = try decoder.decode([CreditsPerson].self, from: data)
return .success(source)
} catch {
Debug.shared.log(message: "Failed to parse JSON: \(error)", type: .error)
return .failure(error)
}
}
}
1 change: 1 addition & 0 deletions Shared/Design/SectionIcons.swift
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ class SectionIcons {
cell.imageView?.clipsToBounds = true
cell.imageView?.layer.borderWidth = 1
cell.imageView?.layer.borderColor = UIColor.lightGray.withAlphaComponent(0.3).cgColor
cell.imageView?.layer.cornerCurve = .continuous
}


Expand Down
36 changes: 32 additions & 4 deletions feather.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
332476EA2C3E905D008C8EF0 /* AboutViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332476E92C3E905D008C8EF0 /* AboutViewController.swift */; };
332476ED2C3E92BC008C8EF0 /* DisplayCollectionTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332476EB2C3E92BC008C8EF0 /* DisplayCollectionTableViewCell.swift */; };
332476EE2C3E92BC008C8EF0 /* DisplayViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 332476EC2C3E92BC008C8EF0 /* DisplayViewController.swift */; };
33275B6C2CD0A598007ED278 /* LicenseViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33275B6B2CD0A590007ED278 /* LicenseViewController.swift */; };
332AE3C02C097F180052F24A /* Feather.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 332AE3BE2C097F180052F24A /* Feather.xcdatamodeld */; };
333912A02BF9816B00E72360 /* CertificateModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3339129F2BF9816B00E72360 /* CertificateModel.swift */; };
33570F612C32B80E008CB560 /* AppsTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 33570F602C32B80E008CB560 /* AppsTableViewCell.swift */; };
Expand Down Expand Up @@ -159,6 +160,7 @@
332476E92C3E905D008C8EF0 /* AboutViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AboutViewController.swift; sourceTree = "<group>"; };
332476EB2C3E92BC008C8EF0 /* DisplayCollectionTableViewCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayCollectionTableViewCell.swift; sourceTree = "<group>"; };
332476EC2C3E92BC008C8EF0 /* DisplayViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DisplayViewController.swift; sourceTree = "<group>"; };
33275B6B2CD0A590007ED278 /* LicenseViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LicenseViewController.swift; sourceTree = "<group>"; };
332AE3BF2C097F180052F24A /* Feather.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = Feather.xcdatamodel; sourceTree = "<group>"; };
3339129F2BF9816B00E72360 /* CertificateModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CertificateModel.swift; sourceTree = "<group>"; };
33570F602C32B80E008CB560 /* AppsTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsTableViewCell.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -352,11 +354,37 @@
isa = PBXGroup;
children = (
332476E92C3E905D008C8EF0 /* AboutViewController.swift */,
33275B6B2CD0A590007ED278 /* LicenseViewController.swift */,
332476E52C3E8E25008C8EF0 /* SettingsCreditsTableCell.swift */,
33E4D8422C6802BB006A1C26 /* SettingsHeaderTableViewCell.swift */,
);
path = About;
sourceTree = "<group>";
};
33275B662CD0A4A6007ED278 /* Server Options */ = {
isa = PBXGroup;
children = (
33E5A5A12CC85CAA00532930 /* ServerOptionsViewController.swift */,
);
path = "Server Options";
sourceTree = "<group>";
};
33275B692CD0A4D8007ED278 /* View Logs */ = {
isa = PBXGroup;
children = (
33E5A5AD2CC8A41E00532930 /* LogsViewController.swift */,
);
path = "View Logs";
sourceTree = "<group>";
};
33275B6A2CD0A4E4007ED278 /* Language */ = {
isa = PBXGroup;
children = (
33E5A5982CC8586E00532930 /* LanguageViewController.swift */,
);
path = Language;
sourceTree = "<group>";
};
336EEE822C324C9B0011188D /* Apps */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -580,17 +608,16 @@
isa = PBXGroup;
children = (
33AC87F02C3B7CBE003D1175 /* SettingsViewController.swift */,
332476E52C3E8E25008C8EF0 /* SettingsCreditsTableCell.swift */,
33E4D8402C67E5C3006A1C26 /* DonationTableViewCell.swift */,
332476E72C3E9044008C8EF0 /* About */,
332476E42C3E8778008C8EF0 /* Display */,
338FFCE22C6950FC006C3BE0 /* AppIcon */,
33E5A5982CC8586E00532930 /* LanguageViewController.swift */,
33275B6A2CD0A4E4007ED278 /* Language */,
33AC87EE2C3B7C3D003D1175 /* Certificates */,
33E5A5A32CC86C7D00532930 /* Signing Options */,
33E5A5A12CC85CAA00532930 /* ServerOptionsViewController.swift */,
33275B662CD0A4A6007ED278 /* Server Options */,
33275B692CD0A4D8007ED278 /* View Logs */,
332476E12C3E874F008C8EF0 /* Reset */,
33E5A5AD2CC8A41E00532930 /* LogsViewController.swift */,
);
path = Settings;
sourceTree = "<group>";
Expand Down Expand Up @@ -1012,6 +1039,7 @@
D0651C392BFEEA4B00D40829 /* signing.cpp in Sources */,
33C0409B2C30B4A100243D90 /* AppDownload.swift in Sources */,
33BA37BA2BF9426100FF530A /* Sources.swift in Sources */,
33275B6C2CD0A598007ED278 /* LicenseViewController.swift in Sources */,
D0651C1C2BFEE97F00D40829 /* json.cpp in Sources */,
339CE28A2C58539300B58502 /* Logger.swift in Sources */,
33C29F202C7BD73800EF7608 /* UIUserInterfaceStyle+allCases.swift in Sources */,
Expand Down
192 changes: 97 additions & 95 deletions iOS/Views/Settings/About/AboutViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,25 @@ import UIKit
import MachO

class AboutViewController: UITableViewController {
let tintColor = Preferences.appTintColor.uiColor


var credits: [CreditsPerson] = []
var creditsSponsors: [CreditsPerson] = []
var fileNames: [String] = []
var tableData =
[

private let sourceGET = SourceGET()

var tableData = [
["Header"],
[],
[String.localized("ABOUT_VIEW_CONTROLLER_CELL_DEVICE_VERSION"), String.localized("ABOUT_VIEW_CONTROLLER_CELL_DEVICE_ARCH"), String.localized("ABOUT_VIEW_CONTROLLER_CELL_APP_VERSION")],
[""],
[]
]

var sectionTitles =
[
var sectionTitles = [
"",
String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_CREDITS"),
String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_DEVICE"),
"Sponsors",
String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_ACKNOWLEDGEMENTS")
]

Expand All @@ -47,19 +51,6 @@ class AboutViewController: UITableViewController {
self.tableView.delegate = self
}

@objc func shareButtonTapped() {
let shareText = "Feather - https://github.com/khcrysalis/feather"
let activityViewController = UIActivityViewController(activityItems: [shareText], applicationActivities: nil)

if let popoverController = activityViewController.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = self.view.bounds
popoverController.permittedArrowDirections = []
}

present(activityViewController, animated: true, completion: nil)
}

fileprivate func setupNavigation() {
self.title = "About"
self.navigationItem.largeTitleDisplayMode = .never
Expand All @@ -72,14 +63,65 @@ class AboutViewController: UITableViewController {
tableData[3] = fileNames
}

let credits = CreditsData.getCreditsData()
var creditsSection: [String] = []
let creditsURL = URL(string: "https://raw.githubusercontent.com/khcrysalis/project-credits/refs/heads/main/feather/credits.json")!
let sponsorsURL = URL(string: "https://raw.githubusercontent.com/khcrysalis/project-credits/refs/heads/main/sponsors/credits.json")!

getURL(url: creditsURL) { result in
switch result {
case .success(let credits):
self.credits = credits
self.tableData[1] = credits.map { $0.name ?? "" }
DispatchQueue.main.async {
self.tableView.reloadSections(IndexSet(integer: 1), with: .automatic)
}
case .failure(_):
Debug.shared.log(message: "Error fetching credits")
}
}

getURL(url: sponsorsURL) { result in
switch result {
case .success(let sponsors):
self.creditsSponsors = sponsors
DispatchQueue.main.async {
self.tableView.reloadSections(IndexSet(integer: 2), with: .automatic)
}
case .failure(_):
Debug.shared.log(message: "Error fetching sponsors")
}
}
}

private func getURL(url: URL, completion: @escaping (Result<[CreditsPerson], Error>) -> Void) {
sourceGET.downloadURL(from: url) { result in
switch result {
case .success((let data, _)):
switch SourceGET().parsec(data: data) {
case .success(let sourceData):
completion(.success(sourceData))
case .failure(let error):
Debug.shared.log(message: "Error parsing data: \(error)")
completion(.failure(error))
}
case .failure(let error):
Debug.shared.log(message: "Error downloading data: \(error)")
completion(.failure(error))
}
}
}


@objc func shareButtonTapped() {
let shareText = "Feather - https://github.com/khcrysalis/feather"
let activityViewController = UIActivityViewController(activityItems: [shareText], applicationActivities: nil)

for _ in credits {
creditsSection.append("Credits Person")
if let popoverController = activityViewController.popoverPresentationController {
popoverController.sourceView = self.view
popoverController.sourceRect = self.view.bounds
popoverController.permittedArrowDirections = []
}

tableData[1] = creditsSection
present(activityViewController, animated: true, completion: nil)
}
}

Expand All @@ -101,10 +143,9 @@ extension AboutViewController {
cell.selectionStyle = .none

let cellText = tableData[indexPath.section][indexPath.row]
cell.textLabel?.text = cellText

switch cellText {
case "Header":
switch indexPath.section {
case 0:
let cell = HeaderTableViewCell()
let appName = Bundle.main.infoDictionary?["CFBundleName"] as? String ?? ""
let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String ?? ""
Expand All @@ -114,105 +155,66 @@ extension AboutViewController {
cell.selectionStyle = .none
cell.configure(withTitle: appName, versionString: versionString)
return cell
case String.localized("ABOUT_VIEW_CONTROLLER_CELL_DEVICE_VERSION"):
cell.detailTextLabel?.text = UIDevice.current.systemVersion
case String.localized("ABOUT_VIEW_CONTROLLER_CELL_DEVICE_ARCH"):
cell.detailTextLabel?.text = String(cString: NXGetLocalArchInfo().pointee.name)
case String.localized("ABOUT_VIEW_CONTROLLER_CELL_APP_VERSION"):
guard let appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String else {
break
}
cell.detailTextLabel?.text = appVersion
case "Build":
break
default:
break
}

if sectionTitles[indexPath.section] == String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_CREDITS") {
case 1:

let personCellIdentifier = "PersonCell"
let personCell = tableView.dequeueReusableCell(withIdentifier: personCellIdentifier) as? PersonCell ?? PersonCell(style: .default, reuseIdentifier: personCellIdentifier)

let developers = CreditsData.getCreditsData()
let developer = developers[indexPath.row]

personCell.configure(with: developer)
let credits = self.credits[indexPath.row]

personCell.configure(with: credits)
if let arrowImage = UIImage(systemName: "arrow.up.forward")?.withTintColor(UIColor.tertiaryLabel, renderingMode: .alwaysOriginal) {
personCell.accessoryView = UIImageView(image: arrowImage)
}
return personCell
}

if sectionTitles[indexPath.section] == String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_ACKNOWLEDGEMENTS") {
case 2:
let personCellIdentifier = "BatchPersonCell"
let personCell = tableView.dequeueReusableCell(withIdentifier: personCellIdentifier) as? BatchPersonCell ?? BatchPersonCell(style: .default, reuseIdentifier: personCellIdentifier)

personCell.configure(with: creditsSponsors)
return personCell
case 3:
let cell = UITableViewCell(style: .default, reuseIdentifier: reuseIdentifier)
cell.textLabel?.text = cellText
cell.accessoryType = .disclosureIndicator
return cell
default:
break
}


return cell
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if sectionTitles[indexPath.section] == String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_CREDITS") {
let developers = CreditsData.getCreditsData()
let developer = developers[indexPath.row]
if let socialLink = developer.socialLink {
let selectedFileName = tableData[indexPath.section][indexPath.row]
switch indexPath.section {
case 1:
let developer = self.credits[indexPath.row]
if let socialLink = URL(string: "https://github.com/\(developer.github)") {
UIApplication.shared.open(socialLink, options: [:], completionHandler: nil)
}
}

let selectedFileName = tableData[indexPath.section][indexPath.row]

if sectionTitles[indexPath.section] == String.localized("ABOUT_VIEW_CONTROLLER_SECTION_TITLE_ACKNOWLEDGEMENTS") {
case 3:
if let fileContents = loadFileContents(fileName: selectedFileName) {
let textViewController = TextViewController()
let textViewController = LicenseViewController()
textViewController.textContent = fileContents
textViewController.titleText = selectedFileName
navigationController?.pushViewController(textViewController, animated: true)
}
default:
break
}

tableView.deselectRow(at: indexPath, animated: true)
}

}

extension AboutViewController {
private func loadFileContents(fileName: String) -> String? {
guard let filePath = Bundle.main.path(forResource: fileName, ofType: ""),
let fileContents = try? String(contentsOfFile: filePath) else {
return nil
}
return fileContents
}

}

class TextViewController: UIViewController {

var textContent: String?
var titleText: String?

override func viewDidLoad() {
super.viewDidLoad()
title = titleText
let textView = UITextView()
textView.text = textContent
textView.isEditable = false
textView.translatesAutoresizingMaskIntoConstraints = false

let monospacedFont = UIFont.monospacedSystemFont(ofSize: 12.0, weight: .regular)
textView.font = monospacedFont

// Scroll to top
textView.setContentOffset(CGPoint.zero, animated: true)
textView.contentInset = UIEdgeInsets(top: 16, left: 16, bottom: 16, right: 16)

view.addSubview(textView)

NSLayoutConstraint.activate([
textView.topAnchor.constraint(equalTo: view.topAnchor),
textView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
textView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
textView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
])
}
}

Loading

0 comments on commit e1fb7ce

Please sign in to comment.