2019-07-24 12:23:54 -07:00
|
|
|
//
|
|
|
|
|
// AppContentViewController.swift
|
|
|
|
|
// AltStore
|
|
|
|
|
//
|
|
|
|
|
// Created by Riley Testut on 7/22/19.
|
|
|
|
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
import UIKit
|
|
|
|
|
|
2020-09-03 16:39:08 -07:00
|
|
|
import AltStoreCore
|
2019-07-24 12:23:54 -07:00
|
|
|
import Roxas
|
|
|
|
|
|
2019-08-20 19:06:03 -05:00
|
|
|
import Nuke
|
|
|
|
|
|
2019-07-24 12:23:54 -07:00
|
|
|
extension AppContentViewController
|
|
|
|
|
{
|
|
|
|
|
private enum Row: Int, CaseIterable
|
|
|
|
|
{
|
|
|
|
|
case subtitle
|
|
|
|
|
case screenshots
|
|
|
|
|
case description
|
|
|
|
|
case versionDescription
|
|
|
|
|
case permissions
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2023-01-04 09:52:12 -05:00
|
|
|
final class AppContentViewController: UITableViewController
|
2019-07-24 12:23:54 -07:00
|
|
|
{
|
2019-07-31 14:07:00 -07:00
|
|
|
var app: StoreApp!
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2024-12-07 17:45:09 +05:30
|
|
|
// private lazy var screenshotsDataSource = self.makeScreenshotsDataSource()
|
2023-10-11 18:13:01 -05:00
|
|
|
private lazy var dateFormatter: DateFormatter = {
|
|
|
|
|
let dateFormatter = DateFormatter()
|
|
|
|
|
dateFormatter.dateStyle = .medium
|
|
|
|
|
dateFormatter.timeStyle = .none
|
|
|
|
|
return dateFormatter
|
|
|
|
|
}()
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2019-07-29 16:03:22 -07:00
|
|
|
private lazy var byteCountFormatter: ByteCountFormatter = {
|
|
|
|
|
let formatter = ByteCountFormatter()
|
|
|
|
|
return formatter
|
|
|
|
|
}()
|
|
|
|
|
|
2019-07-24 12:23:54 -07:00
|
|
|
@IBOutlet private var subtitleLabel: UILabel!
|
2025-02-28 05:09:37 +05:30
|
|
|
// @IBOutlet private var descriptionTextView: CollapsingTextView!
|
|
|
|
|
@IBOutlet private var descriptionTextView: CollapsingMarkdownView!
|
2025-02-27 23:39:03 +05:30
|
|
|
// @IBOutlet private var versionDescriptionTextView: CollapsingTextView!
|
|
|
|
|
@IBOutlet private var versionDescriptionTextView: CollapsingMarkdownView!
|
2019-07-29 16:03:22 -07:00
|
|
|
@IBOutlet private var versionLabel: UILabel!
|
|
|
|
|
@IBOutlet private var versionDateLabel: UILabel!
|
|
|
|
|
@IBOutlet private var sizeLabel: UILabel!
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2023-10-11 18:13:01 -05:00
|
|
|
@IBOutlet private(set) var appScreenshotsViewController: AppScreenshotsViewController!
|
|
|
|
|
@IBOutlet private var appScreenshotsHeightConstraint: NSLayoutConstraint!
|
2023-05-24 15:56:06 -05:00
|
|
|
|
|
|
|
|
@IBOutlet private(set) var appDetailCollectionViewController: AppDetailCollectionViewController!
|
|
|
|
|
@IBOutlet private var appDetailCollectionViewHeightConstraint: NSLayoutConstraint!
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2025-02-27 23:39:03 +05:30
|
|
|
override func viewDidLoad() {
|
2019-07-24 12:23:54 -07:00
|
|
|
super.viewDidLoad()
|
|
|
|
|
|
|
|
|
|
self.tableView.contentInset.bottom = 20
|
2019-10-23 14:19:32 -07:00
|
|
|
|
2019-07-24 12:23:54 -07:00
|
|
|
self.subtitleLabel.text = self.app.subtitle
|
2025-02-28 05:09:37 +05:30
|
|
|
let desc = self.app.localizedDescription
|
|
|
|
|
self.descriptionTextView.text = desc
|
2022-09-12 17:05:55 -07:00
|
|
|
|
2025-02-27 23:39:03 +05:30
|
|
|
if let version = self.app.latestAvailableVersion {
|
|
|
|
|
self.versionDescriptionTextView.text = version.localizedDescription ?? "nil"
|
2023-05-18 14:51:26 -05:00
|
|
|
self.versionLabel.text = String(format: NSLocalizedString("Version %@", comment: ""), version.localizedVersion)
|
2023-10-16 18:27:48 -05:00
|
|
|
self.versionDateLabel.text = Date().relativeDateString(since: version.date)
|
2025-02-27 23:39:03 +05:30
|
|
|
self.sizeLabel.text = ByteCountFormatter.string(fromByteCount: version.size, countStyle: .file)
|
|
|
|
|
} else {
|
|
|
|
|
self.versionDescriptionTextView.text = "nil"
|
2022-09-12 17:05:55 -07:00
|
|
|
self.versionLabel.text = nil
|
|
|
|
|
self.versionDateLabel.text = nil
|
2025-02-27 23:39:03 +05:30
|
|
|
self.sizeLabel.text = ByteCountFormatter.string(fromByteCount: 0, countStyle: .file)
|
2022-09-12 17:05:55 -07:00
|
|
|
}
|
2019-07-24 12:23:54 -07:00
|
|
|
|
|
|
|
|
self.descriptionTextView.maximumNumberOfLines = 5
|
2025-02-28 05:09:37 +05:30
|
|
|
self.versionDescriptionTextView.maximumNumberOfLines = 5
|
2025-02-27 23:39:03 +05:30
|
|
|
|
2025-02-28 05:09:37 +05:30
|
|
|
self.descriptionTextView.toggleButton.addTarget(self, action: #selector(AppContentViewController.toggleCollapsingSection(_:)), for: .primaryActionTriggered)
|
|
|
|
|
self.versionDescriptionTextView.toggleButton.addTarget(self, action: #selector(AppContentViewController.toggleCollapsingSection(_:)), for: .primaryActionTriggered)
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func viewDidLayoutSubviews()
|
|
|
|
|
{
|
|
|
|
|
super.viewDidLayoutSubviews()
|
|
|
|
|
|
2023-10-11 18:13:01 -05:00
|
|
|
var needsTableViewUpdate = false
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2023-10-11 18:13:01 -05:00
|
|
|
let screenshotsHeight = self.appScreenshotsViewController.collectionView.contentSize.height
|
|
|
|
|
if self.appScreenshotsHeightConstraint.constant != screenshotsHeight && screenshotsHeight > 0
|
|
|
|
|
{
|
|
|
|
|
self.appScreenshotsHeightConstraint.constant = screenshotsHeight
|
|
|
|
|
needsTableViewUpdate = true
|
|
|
|
|
}
|
2019-07-24 12:23:54 -07:00
|
|
|
|
2023-05-24 15:56:06 -05:00
|
|
|
let permissionsHeight = self.appDetailCollectionViewController.collectionView.contentSize.height
|
|
|
|
|
if self.appDetailCollectionViewHeightConstraint.constant != permissionsHeight && permissionsHeight > 0
|
|
|
|
|
{
|
|
|
|
|
self.appDetailCollectionViewHeightConstraint.constant = permissionsHeight
|
2023-10-11 18:13:01 -05:00
|
|
|
needsTableViewUpdate = true
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if needsTableViewUpdate
|
|
|
|
|
{
|
2023-05-25 18:03:21 -05:00
|
|
|
UIView.performWithoutAnimation {
|
|
|
|
|
// Update row height without animation.
|
|
|
|
|
self.tableView.beginUpdates()
|
|
|
|
|
self.tableView.endUpdates()
|
|
|
|
|
}
|
2023-05-24 15:56:06 -05:00
|
|
|
}
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension AppContentViewController
|
|
|
|
|
{
|
2023-10-11 18:13:01 -05:00
|
|
|
@IBSegueAction
|
|
|
|
|
func makeAppScreenshotsViewController(_ coder: NSCoder, sender: Any?) -> UIViewController?
|
2019-07-24 12:23:54 -07:00
|
|
|
{
|
2023-10-11 18:13:01 -05:00
|
|
|
let appScreenshotsViewController = AppScreenshotsViewController(app: self.app, coder: coder)
|
|
|
|
|
self.appScreenshotsViewController = appScreenshotsViewController
|
|
|
|
|
return appScreenshotsViewController
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func makePermissionsDataSource() -> RSTArrayCollectionViewDataSource<AppPermission>
|
|
|
|
|
{
|
2023-05-12 18:26:24 -05:00
|
|
|
let dataSource = RSTArrayCollectionViewDataSource(items: Array(self.app.permissions))
|
2019-07-24 12:23:54 -07:00
|
|
|
dataSource.cellConfigurationHandler = { (cell, permission, indexPath) in
|
|
|
|
|
let cell = cell as! PermissionCollectionViewCell
|
2023-05-12 18:26:24 -05:00
|
|
|
// cell.button.setImage(permission.type.icon, for: .normal)
|
|
|
|
|
// cell.button.tintColor = .label
|
|
|
|
|
// cell.textLabel.text = permission.type.localizedShortName ?? permission.type.localizedName
|
|
|
|
|
|
|
|
|
|
let icon = UIImage(systemName: permission.symbolName ?? "lock")
|
|
|
|
|
cell.button.setImage(icon, for: .normal)
|
|
|
|
|
|
|
|
|
|
cell.textLabel.text = permission.localizedDisplayName
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return dataSource
|
|
|
|
|
}
|
2023-05-24 15:56:06 -05:00
|
|
|
|
|
|
|
|
@IBSegueAction
|
|
|
|
|
func makeAppDetailCollectionViewController(_ coder: NSCoder, sender: Any?) -> UIViewController?
|
|
|
|
|
{
|
|
|
|
|
let appDetailViewController = AppDetailCollectionViewController(app: self.app, coder: coder)
|
|
|
|
|
self.appDetailCollectionViewController = appDetailViewController
|
|
|
|
|
return appDetailViewController
|
|
|
|
|
}
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private extension AppContentViewController
|
|
|
|
|
{
|
|
|
|
|
@objc func toggleCollapsingSection(_ sender: UIButton)
|
|
|
|
|
{
|
|
|
|
|
let indexPath: IndexPath
|
|
|
|
|
|
|
|
|
|
switch sender
|
|
|
|
|
{
|
2025-02-28 05:09:37 +05:30
|
|
|
case self.descriptionTextView.toggleButton:
|
2025-02-27 23:39:03 +05:30
|
|
|
indexPath = IndexPath(row: Row.description.rawValue, section: 0)
|
|
|
|
|
|
|
|
|
|
case self.versionDescriptionTextView.toggleButton:
|
|
|
|
|
indexPath = IndexPath(row: Row.versionDescription.rawValue, section: 0)
|
2025-02-28 05:09:37 +05:30
|
|
|
|
2019-07-24 12:23:54 -07:00
|
|
|
default: return
|
|
|
|
|
}
|
|
|
|
|
|
2025-02-28 05:09:37 +05:30
|
|
|
// Disable animations to prevent some potentially strange ones.
|
|
|
|
|
UIView.performWithoutAnimation {
|
|
|
|
|
self.tableView.reloadRows(at: [indexPath], with: .none)
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
extension AppContentViewController
|
|
|
|
|
{
|
|
|
|
|
override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
|
|
|
|
|
{
|
|
|
|
|
cell.tintColor = self.app.tintColor
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
|
|
|
|
|
{
|
2022-04-11 12:31:02 -07:00
|
|
|
switch Row.allCases[indexPath.row]
|
|
|
|
|
{
|
|
|
|
|
case .screenshots:
|
2025-02-08 13:11:27 +05:30
|
|
|
guard !self.app.allScreenshots.isEmpty else { return 0.0 }
|
2023-10-11 18:13:01 -05:00
|
|
|
return UITableView.automaticDimension
|
2022-04-11 12:31:02 -07:00
|
|
|
|
|
|
|
|
case .permissions:
|
|
|
|
|
guard !self.app.permissions.isEmpty else { return 0.0 }
|
2023-05-24 15:56:06 -05:00
|
|
|
return UITableView.automaticDimension
|
2022-04-11 12:31:02 -07:00
|
|
|
|
|
|
|
|
default:
|
|
|
|
|
return super.tableView(tableView, heightForRowAt: indexPath)
|
|
|
|
|
}
|
2019-07-24 12:23:54 -07:00
|
|
|
}
|
|
|
|
|
}
|