mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
[AltStore] Revises AppViewController UI
- Fades in navigation bar as user scrolls down - Displays version number, version date, and app size
This commit is contained in:
@@ -168,6 +168,7 @@
|
|||||||
BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1E22A1A9EC000B7ED1 /* node_list.c */; };
|
BFD52C2122A1A9EC000B7ED1 /* node_list.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1E22A1A9EC000B7ED1 /* node_list.c */; };
|
||||||
BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1F22A1A9EC000B7ED1 /* cnary.c */; };
|
BFD52C2222A1A9EC000B7ED1 /* cnary.c in Sources */ = {isa = PBXBuildFile; fileRef = BFD52C1F22A1A9EC000B7ED1 /* cnary.c */; };
|
||||||
BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */; };
|
BFD6B03322DFF20800B86064 /* MyAppsComponents.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */; };
|
||||||
|
BFDB5B1622EE90D300F74113 /* Date+RelativeDate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */; };
|
||||||
BFDB69FD22A9A7B7007EA6D6 /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB69FC22A9A7B7007EA6D6 /* AccountViewController.swift */; };
|
BFDB69FD22A9A7B7007EA6D6 /* AccountViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB69FC22A9A7B7007EA6D6 /* AccountViewController.swift */; };
|
||||||
BFDB6A0522A9AFB2007EA6D6 /* Fetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */; };
|
BFDB6A0522A9AFB2007EA6D6 /* Fetchable.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */; };
|
||||||
BFDB6A0822AAED73007EA6D6 /* ResignAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB6A0722AAED73007EA6D6 /* ResignAppOperation.swift */; };
|
BFDB6A0822AAED73007EA6D6 /* ResignAppOperation.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFDB6A0722AAED73007EA6D6 /* ResignAppOperation.swift */; };
|
||||||
@@ -416,6 +417,7 @@
|
|||||||
BFD52C1E22A1A9EC000B7ED1 /* node_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node_list.c; path = Dependencies/libplist/libcnary/node_list.c; sourceTree = SOURCE_ROOT; };
|
BFD52C1E22A1A9EC000B7ED1 /* node_list.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = node_list.c; path = Dependencies/libplist/libcnary/node_list.c; sourceTree = SOURCE_ROOT; };
|
||||||
BFD52C1F22A1A9EC000B7ED1 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; };
|
BFD52C1F22A1A9EC000B7ED1 /* cnary.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; name = cnary.c; path = Dependencies/libplist/libcnary/cnary.c; sourceTree = SOURCE_ROOT; };
|
||||||
BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAppsComponents.swift; sourceTree = "<group>"; };
|
BFD6B03222DFF20800B86064 /* MyAppsComponents.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAppsComponents.swift; sourceTree = "<group>"; };
|
||||||
|
BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Date+RelativeDate.swift"; sourceTree = "<group>"; };
|
||||||
BFDB69FC22A9A7B7007EA6D6 /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = "<group>"; };
|
BFDB69FC22A9A7B7007EA6D6 /* AccountViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AccountViewController.swift; sourceTree = "<group>"; };
|
||||||
BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fetchable.swift; sourceTree = "<group>"; };
|
BFDB6A0422A9AFB2007EA6D6 /* Fetchable.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Fetchable.swift; sourceTree = "<group>"; };
|
||||||
BFDB6A0722AAED73007EA6D6 /* ResignAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResignAppOperation.swift; sourceTree = "<group>"; };
|
BFDB6A0722AAED73007EA6D6 /* ResignAppOperation.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ResignAppOperation.swift; sourceTree = "<group>"; };
|
||||||
@@ -855,6 +857,7 @@
|
|||||||
BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */,
|
BFB1169A2293274D00BB457C /* JSONDecoder+ManagedObjectContext.swift */,
|
||||||
BF43002F22A71C960051E2BC /* UserDefaults+AltStore.swift */,
|
BF43002F22A71C960051E2BC /* UserDefaults+AltStore.swift */,
|
||||||
BF9ABA4E22DD41A9008935CF /* UIColor+Hex.swift */,
|
BF9ABA4E22DD41A9008935CF /* UIColor+Hex.swift */,
|
||||||
|
BFDB5B1522EE90D300F74113 /* Date+RelativeDate.swift */,
|
||||||
);
|
);
|
||||||
path = Extensions;
|
path = Extensions;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -1311,6 +1314,7 @@
|
|||||||
BFE6326C22A86FF300F30809 /* AuthenticationOperation.swift in Sources */,
|
BFE6326C22A86FF300F30809 /* AuthenticationOperation.swift in Sources */,
|
||||||
BFDB6A0522A9AFB2007EA6D6 /* Fetchable.swift in Sources */,
|
BFDB6A0522A9AFB2007EA6D6 /* Fetchable.swift in Sources */,
|
||||||
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */,
|
BFD2479F2284FBD000981D42 /* UIColor+AltStore.swift in Sources */,
|
||||||
|
BFDB5B1622EE90D300F74113 /* Date+RelativeDate.swift in Sources */,
|
||||||
BF770E5622BC3C03002A40FE /* Server.swift in Sources */,
|
BF770E5622BC3C03002A40FE /* Server.swift in Sources */,
|
||||||
BF43003022A71C960051E2BC /* UserDefaults+AltStore.swift in Sources */,
|
BF43003022A71C960051E2BC /* UserDefaults+AltStore.swift in Sources */,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -29,9 +29,24 @@ class AppContentViewController: UITableViewController
|
|||||||
private lazy var screenshotsDataSource = self.makeScreenshotsDataSource()
|
private lazy var screenshotsDataSource = self.makeScreenshotsDataSource()
|
||||||
private lazy var permissionsDataSource = self.makePermissionsDataSource()
|
private lazy var permissionsDataSource = self.makePermissionsDataSource()
|
||||||
|
|
||||||
|
private lazy var dateFormatter: DateFormatter = {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateStyle = .medium
|
||||||
|
dateFormatter.timeStyle = .none
|
||||||
|
return dateFormatter
|
||||||
|
}()
|
||||||
|
|
||||||
|
private lazy var byteCountFormatter: ByteCountFormatter = {
|
||||||
|
let formatter = ByteCountFormatter()
|
||||||
|
return formatter
|
||||||
|
}()
|
||||||
|
|
||||||
@IBOutlet private var subtitleLabel: UILabel!
|
@IBOutlet private var subtitleLabel: UILabel!
|
||||||
@IBOutlet private var descriptionTextView: CollapsingTextView!
|
@IBOutlet private var descriptionTextView: CollapsingTextView!
|
||||||
@IBOutlet private var versionDescriptionTextView: CollapsingTextView!
|
@IBOutlet private var versionDescriptionTextView: CollapsingTextView!
|
||||||
|
@IBOutlet private var versionLabel: UILabel!
|
||||||
|
@IBOutlet private var versionDateLabel: UILabel!
|
||||||
|
@IBOutlet private var sizeLabel: UILabel!
|
||||||
|
|
||||||
@IBOutlet private var screenshotsCollectionView: UICollectionView!
|
@IBOutlet private var screenshotsCollectionView: UICollectionView!
|
||||||
@IBOutlet private var permissionsCollectionView: UICollectionView!
|
@IBOutlet private var permissionsCollectionView: UICollectionView!
|
||||||
@@ -63,6 +78,9 @@ class AppContentViewController: UITableViewController
|
|||||||
self.subtitleLabel.text = self.app.subtitle
|
self.subtitleLabel.text = self.app.subtitle
|
||||||
self.descriptionTextView.text = self.app.localizedDescription
|
self.descriptionTextView.text = self.app.localizedDescription
|
||||||
self.versionDescriptionTextView.text = self.app.versionDescription
|
self.versionDescriptionTextView.text = self.app.versionDescription
|
||||||
|
self.versionLabel.text = String(format: NSLocalizedString("Version %@", comment: ""), self.app.version)
|
||||||
|
self.versionDateLabel.text = Date().relativeDateString(since: self.app.versionDate, dateFormatter: self.dateFormatter)
|
||||||
|
self.sizeLabel.text = self.byteCountFormatter.string(fromByteCount: Int64(self.app.size))
|
||||||
|
|
||||||
self.descriptionTextView.maximumNumberOfLines = 5
|
self.descriptionTextView.maximumNumberOfLines = 5
|
||||||
self.descriptionTextView.moreButton.addTarget(self, action: #selector(AppContentViewController.toggleCollapsingSection(_:)), for: .primaryActionTriggered)
|
self.descriptionTextView.moreButton.addTarget(self, action: #selector(AppContentViewController.toggleCollapsingSection(_:)), for: .primaryActionTriggered)
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ class AppViewController: UIViewController
|
|||||||
private var contentViewControllerShadowView: UIView!
|
private var contentViewControllerShadowView: UIView!
|
||||||
|
|
||||||
private var blurAnimator: UIViewPropertyAnimator?
|
private var blurAnimator: UIViewPropertyAnimator?
|
||||||
|
private var navigationBarAnimator: UIViewPropertyAnimator?
|
||||||
|
|
||||||
private var contentSizeObservation: NSKeyValueObservation?
|
private var contentSizeObservation: NSKeyValueObservation?
|
||||||
|
|
||||||
@@ -38,13 +39,21 @@ class AppViewController: UIViewController
|
|||||||
@IBOutlet private var backgroundAppIconImageView: UIImageView!
|
@IBOutlet private var backgroundAppIconImageView: UIImageView!
|
||||||
@IBOutlet private var backgroundBlurView: UIVisualEffectView!
|
@IBOutlet private var backgroundBlurView: UIVisualEffectView!
|
||||||
|
|
||||||
private var _isEnteringForeground = false
|
@IBOutlet private var navigationBarTitleView: UIView!
|
||||||
|
@IBOutlet private var navigationBarDownloadButton: PillButton!
|
||||||
|
@IBOutlet private var navigationBarAppIconImageView: UIImageView!
|
||||||
|
@IBOutlet private var navigationBarAppNameLabel: UILabel!
|
||||||
|
|
||||||
|
private var _shouldResetLayout = false
|
||||||
private var _backgroundBlurEffect: UIBlurEffect?
|
private var _backgroundBlurEffect: UIBlurEffect?
|
||||||
private var _backgroundBlurTintColor: UIColor?
|
private var _backgroundBlurTintColor: UIColor?
|
||||||
|
|
||||||
override func viewDidLoad()
|
override func viewDidLoad()
|
||||||
{
|
{
|
||||||
super.viewDidLoad()
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
self.navigationBarTitleView.sizeToFit()
|
||||||
|
self.navigationItem.titleView = self.navigationBarTitleView
|
||||||
|
|
||||||
self.contentViewControllerShadowView = UIView()
|
self.contentViewControllerShadowView = UIView()
|
||||||
self.contentViewControllerShadowView.backgroundColor = .white
|
self.contentViewControllerShadowView.backgroundColor = .white
|
||||||
@@ -75,14 +84,21 @@ class AppViewController: UIViewController
|
|||||||
self.developerLabel.text = self.app.developerName
|
self.developerLabel.text = self.app.developerName
|
||||||
self.developerLabel.textColor = self.app.tintColor
|
self.developerLabel.textColor = self.app.tintColor
|
||||||
self.appIconImageView.image = UIImage(named: self.app.iconName)
|
self.appIconImageView.image = UIImage(named: self.app.iconName)
|
||||||
|
self.appIconImageView.tintColor = self.app.tintColor
|
||||||
self.downloadButton.tintColor = self.app.tintColor
|
self.downloadButton.tintColor = self.app.tintColor
|
||||||
self.backgroundAppIconImageView.image = UIImage(named: self.app.iconName)
|
self.backgroundAppIconImageView.image = UIImage(named: self.app.iconName)
|
||||||
|
|
||||||
self.backButtonContainerView.tintColor = self.app.tintColor
|
self.backButtonContainerView.tintColor = self.app.tintColor
|
||||||
|
|
||||||
self.contentSizeObservation = self.contentViewController.tableView.observe(\.contentSize) { (tableView, change) in
|
self.navigationController?.navigationBar.tintColor = self.app.tintColor
|
||||||
self.view.setNeedsLayout()
|
self.navigationBarDownloadButton.tintColor = self.app.tintColor
|
||||||
self.view.layoutIfNeeded()
|
self.navigationBarAppNameLabel.text = self.app.name
|
||||||
|
self.navigationBarAppIconImageView.image = UIImage(named: self.app.iconName)
|
||||||
|
self.navigationBarAppIconImageView.tintColor = self.app.tintColor
|
||||||
|
|
||||||
|
self.contentSizeObservation = self.contentViewController.tableView.observe(\.contentSize) { [weak self] (tableView, change) in
|
||||||
|
self?.view.setNeedsLayout()
|
||||||
|
self?.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
@@ -113,7 +129,9 @@ class AppViewController: UIViewController
|
|||||||
{
|
{
|
||||||
super.viewDidAppear(animated)
|
super.viewDidAppear(animated)
|
||||||
|
|
||||||
self.hideNavigationBar()
|
self._shouldResetLayout = true
|
||||||
|
self.view.setNeedsLayout()
|
||||||
|
self.view.layoutIfNeeded()
|
||||||
}
|
}
|
||||||
|
|
||||||
override func viewWillDisappear(_ animated: Bool)
|
override func viewWillDisappear(_ animated: Bool)
|
||||||
@@ -130,17 +148,23 @@ class AppViewController: UIViewController
|
|||||||
self.transitionCoordinator?.animate(alongsideTransition: { (context) in
|
self.transitionCoordinator?.animate(alongsideTransition: { (context) in
|
||||||
self.showNavigationBar(for: navigationController)
|
self.showNavigationBar(for: navigationController)
|
||||||
}, completion: { (context) in
|
}, completion: { (context) in
|
||||||
if context.isCancelled
|
if !context.isCancelled
|
||||||
{
|
|
||||||
self.hideNavigationBar(for: navigationController)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
self.showNavigationBar(for: navigationController)
|
self.showNavigationBar(for: navigationController)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func viewDidDisappear(_ animated: Bool)
|
||||||
|
{
|
||||||
|
super.viewDidDisappear(animated)
|
||||||
|
|
||||||
|
if self.navigationController == nil
|
||||||
|
{
|
||||||
|
self.resetNavigationBarAnimation()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
|
||||||
{
|
{
|
||||||
guard segue.identifier == "embedAppContentViewController" else { return }
|
guard segue.identifier == "embedAppContentViewController" else { return }
|
||||||
@@ -153,9 +177,9 @@ class AppViewController: UIViewController
|
|||||||
{
|
{
|
||||||
super.viewDidLayoutSubviews()
|
super.viewDidLayoutSubviews()
|
||||||
|
|
||||||
if self._isEnteringForeground
|
if self._shouldResetLayout
|
||||||
{
|
{
|
||||||
// Returning from background messes up some of our UI, so reset affected components now.
|
// Various events can cause UI to mess up, so reset affected components now.
|
||||||
|
|
||||||
if self.navigationController?.topViewController == self
|
if self.navigationController?.topViewController == self
|
||||||
{
|
{
|
||||||
@@ -164,16 +188,20 @@ class AppViewController: UIViewController
|
|||||||
|
|
||||||
self.prepareBlur()
|
self.prepareBlur()
|
||||||
|
|
||||||
self._isEnteringForeground = false
|
// Reset navigation bar animation, and create a new one later in this method if necessary.
|
||||||
|
self.resetNavigationBarAnimation()
|
||||||
|
|
||||||
|
self._shouldResetLayout = false
|
||||||
}
|
}
|
||||||
|
|
||||||
let statusBarHeight = UIApplication.shared.statusBarFrame.height
|
let statusBarHeight = UIApplication.shared.statusBarFrame.height
|
||||||
|
let cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
|
||||||
|
|
||||||
let inset = 12 as CGFloat
|
let inset = 12 as CGFloat
|
||||||
let padding = 20 as CGFloat
|
let padding = 20 as CGFloat
|
||||||
|
|
||||||
let backButtonSize = self.backButton.sizeThatFits(CGSize(width: 1000, height: 1000))
|
let backButtonSize = self.backButton.sizeThatFits(CGSize(width: 1000, height: 1000))
|
||||||
let backButtonFrame = CGRect(x: inset, y: statusBarHeight,
|
var backButtonFrame = CGRect(x: inset, y: statusBarHeight,
|
||||||
width: backButtonSize.width + 20, height: backButtonSize.height + 20)
|
width: backButtonSize.width + 20, height: backButtonSize.height + 20)
|
||||||
|
|
||||||
var headerFrame = CGRect(x: inset, y: 0, width: self.view.bounds.width - inset * 2, height: self.headerView.bounds.height)
|
var headerFrame = CGRect(x: inset, y: 0, width: self.view.bounds.width - inset * 2, height: self.headerView.bounds.height)
|
||||||
@@ -183,58 +211,80 @@ class AppViewController: UIViewController
|
|||||||
let minimumHeaderY = backButtonFrame.maxY + 8
|
let minimumHeaderY = backButtonFrame.maxY + 8
|
||||||
|
|
||||||
let minimumContentY = minimumHeaderY + headerFrame.height + padding
|
let minimumContentY = minimumHeaderY + headerFrame.height + padding
|
||||||
let maximumContentY = self.view.bounds.width * 0.75
|
let maximumContentY = self.view.bounds.width * 0.667
|
||||||
|
|
||||||
// A full blur is too much, so we reduce the visible blur by 0.3, resulting in 70% blur.
|
// A full blur is too much, so we reduce the visible blur by 0.3, resulting in 70% blur.
|
||||||
let minimumBlurFraction = 0.3 as CGFloat
|
let minimumBlurFraction = 0.3 as CGFloat
|
||||||
|
|
||||||
let difference = (maximumContentY - minimumContentY)
|
contentFrame.origin.y = maximumContentY - self.scrollView.contentOffset.y
|
||||||
|
headerFrame.origin.y = contentFrame.origin.y - padding - headerFrame.height
|
||||||
|
|
||||||
if self.scrollView.contentOffset.y > difference
|
// Stretch the app icon image to fill additional vertical space if necessary.
|
||||||
|
let height = max(contentFrame.origin.y + cornerRadius * 2, backgroundIconFrame.height)
|
||||||
|
backgroundIconFrame.size.height = height
|
||||||
|
|
||||||
|
let blurThreshold = 0 as CGFloat
|
||||||
|
if self.scrollView.contentOffset.y < blurThreshold
|
||||||
{
|
{
|
||||||
// Full screen
|
// Determine how much to lessen blur by.
|
||||||
|
|
||||||
headerFrame.origin.y = minimumHeaderY
|
let range = 75 as CGFloat
|
||||||
contentFrame.origin.y = minimumContentY
|
let difference = -self.scrollView.contentOffset.y
|
||||||
backgroundIconFrame.origin.y = 0
|
|
||||||
|
|
||||||
self.contentViewController.tableView.contentOffset.y = self.scrollView.contentOffset.y - difference
|
let fraction = min(difference, range) / range
|
||||||
|
|
||||||
|
let fractionComplete = (fraction * (1.0 - minimumBlurFraction)) + minimumBlurFraction
|
||||||
|
self.blurAnimator?.fractionComplete = fractionComplete
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Partial screen
|
// Set blur to default.
|
||||||
|
|
||||||
contentFrame.origin.y = maximumContentY - self.scrollView.contentOffset.y
|
self.blurAnimator?.fractionComplete = minimumBlurFraction
|
||||||
headerFrame.origin.y = contentFrame.origin.y - padding - headerFrame.height
|
|
||||||
|
|
||||||
let cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
|
|
||||||
|
|
||||||
// Stretch the app icon image to fill additional vertical space if necessary.
|
|
||||||
let height = max(contentFrame.origin.y + cornerRadius * 2, backgroundIconFrame.height)
|
|
||||||
backgroundIconFrame.size.height = height
|
|
||||||
|
|
||||||
// Keep content table view's content offset at the top.
|
|
||||||
self.contentViewController.tableView.contentOffset.y = 0
|
|
||||||
|
|
||||||
if self.scrollView.contentOffset.y < 0
|
|
||||||
{
|
|
||||||
// Determine how much to lessen blur by.
|
|
||||||
|
|
||||||
let range = 75 as CGFloat
|
|
||||||
|
|
||||||
let fraction = min(-self.scrollView.contentOffset.y, range) / range
|
|
||||||
|
|
||||||
let fractionComplete = (fraction * (1.0 - minimumBlurFraction)) + minimumBlurFraction
|
|
||||||
self.blurAnimator?.fractionComplete = fractionComplete
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Set blur to default.
|
|
||||||
|
|
||||||
self.blurAnimator?.fractionComplete = minimumBlurFraction
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Animate navigation bar.
|
||||||
|
let showNavigationBarThreshold = (maximumContentY - minimumContentY) + backButtonFrame.origin.y
|
||||||
|
if self.scrollView.contentOffset.y > showNavigationBarThreshold
|
||||||
|
{
|
||||||
|
if self.navigationBarAnimator == nil
|
||||||
|
{
|
||||||
|
self.prepareNavigationBarAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
let difference = self.scrollView.contentOffset.y - showNavigationBarThreshold
|
||||||
|
let range = (headerFrame.height + padding) - (self.navigationController?.navigationBar.bounds.height ?? self.view.safeAreaInsets.top)
|
||||||
|
|
||||||
|
let fractionComplete = min(difference, range) / range
|
||||||
|
self.navigationBarAnimator?.fractionComplete = fractionComplete
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.resetNavigationBarAnimation()
|
||||||
|
}
|
||||||
|
|
||||||
|
let beginMovingBackButtonThreshold = (maximumContentY - minimumContentY)
|
||||||
|
if self.scrollView.contentOffset.y > beginMovingBackButtonThreshold
|
||||||
|
{
|
||||||
|
let difference = self.scrollView.contentOffset.y - beginMovingBackButtonThreshold
|
||||||
|
backButtonFrame.origin.y -= difference
|
||||||
|
}
|
||||||
|
|
||||||
|
let pinContentToTopThreshold = maximumContentY
|
||||||
|
if self.scrollView.contentOffset.y > pinContentToTopThreshold
|
||||||
|
{
|
||||||
|
contentFrame.origin.y = 0
|
||||||
|
backgroundIconFrame.origin.y = 0
|
||||||
|
|
||||||
|
let difference = self.scrollView.contentOffset.y - pinContentToTopThreshold
|
||||||
|
self.contentViewController.tableView.contentOffset.y = difference
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Keep content table view's content offset at the top.
|
||||||
|
self.contentViewController.tableView.contentOffset.y = 0
|
||||||
|
}
|
||||||
|
|
||||||
// Keep background app icon centered in gap between top of content and top of screen.
|
// Keep background app icon centered in gap between top of content and top of screen.
|
||||||
backgroundIconFrame.origin.y = (contentFrame.origin.y / 2) - backgroundIconFrame.height / 2
|
backgroundIconFrame.origin.y = (contentFrame.origin.y / 2) - backgroundIconFrame.height / 2
|
||||||
|
|
||||||
@@ -256,7 +306,7 @@ class AppViewController: UIViewController
|
|||||||
let contentOffset = self.scrollView.contentOffset
|
let contentOffset = self.scrollView.contentOffset
|
||||||
|
|
||||||
var contentSize = self.contentViewController.tableView.contentSize
|
var contentSize = self.contentViewController.tableView.contentSize
|
||||||
contentSize.height += minimumContentY + self.view.safeAreaInsets.bottom + self.contentViewController.tableView.contentInset.bottom
|
contentSize.height += maximumContentY
|
||||||
|
|
||||||
self.scrollView.contentSize = contentSize
|
self.scrollView.contentSize = contentSize
|
||||||
self.scrollView.contentOffset = contentOffset
|
self.scrollView.contentOffset = contentOffset
|
||||||
@@ -265,6 +315,7 @@ class AppViewController: UIViewController
|
|||||||
deinit
|
deinit
|
||||||
{
|
{
|
||||||
self.blurAnimator?.stopAnimation(true)
|
self.blurAnimator?.stopAnimation(true)
|
||||||
|
self.navigationBarAnimator?.stopAnimation(true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,21 +323,29 @@ private extension AppViewController
|
|||||||
{
|
{
|
||||||
func update()
|
func update()
|
||||||
{
|
{
|
||||||
self.downloadButton.isIndicatingActivity = false
|
for button in [self.downloadButton!, self.navigationBarDownloadButton!]
|
||||||
|
|
||||||
if self.app.installedApp == nil
|
|
||||||
{
|
{
|
||||||
self.downloadButton.setTitle(NSLocalizedString("FREE", comment: ""), for: .normal)
|
button.tintColor = self.app.tintColor
|
||||||
self.downloadButton.isInverted = false
|
button.isIndicatingActivity = false
|
||||||
}
|
|
||||||
else
|
if self.app.installedApp == nil
|
||||||
{
|
{
|
||||||
self.downloadButton.setTitle(NSLocalizedString("OPEN", comment: ""), for: .normal)
|
button.setTitle(NSLocalizedString("FREE", comment: ""), for: .normal)
|
||||||
self.downloadButton.isInverted = true
|
button.isInverted = false
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
button.setTitle(NSLocalizedString("OPEN", comment: ""), for: .normal)
|
||||||
|
button.isInverted = true
|
||||||
|
}
|
||||||
|
|
||||||
|
let progress = AppManager.shared.installationProgress(for: self.app)
|
||||||
|
button.progress = progress
|
||||||
}
|
}
|
||||||
|
|
||||||
let progress = AppManager.shared.installationProgress(for: self.app)
|
let barButtonItem = self.navigationItem.rightBarButtonItem
|
||||||
self.downloadButton.progress = progress
|
self.navigationItem.rightBarButtonItem = nil
|
||||||
|
self.navigationItem.rightBarButtonItem = barButtonItem
|
||||||
}
|
}
|
||||||
|
|
||||||
func showNavigationBar(for navigationController: UINavigationController? = nil)
|
func showNavigationBar(for navigationController: UINavigationController? = nil)
|
||||||
@@ -294,7 +353,8 @@ private extension AppViewController
|
|||||||
let navigationController = navigationController ?? self.navigationController
|
let navigationController = navigationController ?? self.navigationController
|
||||||
navigationController?.navigationBar.barStyle = .default
|
navigationController?.navigationBar.barStyle = .default
|
||||||
navigationController?.navigationBar.alpha = 1.0
|
navigationController?.navigationBar.alpha = 1.0
|
||||||
navigationController?.navigationBar.setBackgroundImage(nil, for: .default)
|
navigationController?.navigationBar.barTintColor = .white
|
||||||
|
navigationController?.navigationBar.tintColor = .altGreen
|
||||||
}
|
}
|
||||||
|
|
||||||
func hideNavigationBar(for navigationController: UINavigationController? = nil)
|
func hideNavigationBar(for navigationController: UINavigationController? = nil)
|
||||||
@@ -302,7 +362,7 @@ private extension AppViewController
|
|||||||
let navigationController = navigationController ?? self.navigationController
|
let navigationController = navigationController ?? self.navigationController
|
||||||
navigationController?.navigationBar.barStyle = .black
|
navigationController?.navigationBar.barStyle = .black
|
||||||
navigationController?.navigationBar.alpha = 0.0
|
navigationController?.navigationBar.alpha = 0.0
|
||||||
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
|
navigationController?.navigationBar.barTintColor = .white
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareBlur()
|
func prepareBlur()
|
||||||
@@ -315,14 +375,41 @@ private extension AppViewController
|
|||||||
self.backgroundBlurView.effect = self._backgroundBlurEffect
|
self.backgroundBlurView.effect = self._backgroundBlurEffect
|
||||||
self.backgroundBlurView.contentView.backgroundColor = self._backgroundBlurTintColor
|
self.backgroundBlurView.contentView.backgroundColor = self._backgroundBlurTintColor
|
||||||
|
|
||||||
self.blurAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) {
|
self.blurAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) { [weak self] in
|
||||||
self.backgroundBlurView.effect = nil
|
self?.backgroundBlurView.effect = nil
|
||||||
self.backgroundBlurView.contentView.backgroundColor = .clear
|
self?.backgroundBlurView.contentView.backgroundColor = .clear
|
||||||
}
|
}
|
||||||
|
|
||||||
self.blurAnimator?.startAnimation()
|
self.blurAnimator?.startAnimation()
|
||||||
self.blurAnimator?.pauseAnimation()
|
self.blurAnimator?.pauseAnimation()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func prepareNavigationBarAnimation()
|
||||||
|
{
|
||||||
|
self.resetNavigationBarAnimation()
|
||||||
|
|
||||||
|
self.navigationBarAnimator = UIViewPropertyAnimator(duration: 1.0, curve: .linear) { [weak self] in
|
||||||
|
self?.showNavigationBar()
|
||||||
|
self?.navigationController?.navigationBar.tintColor = self?.app.tintColor
|
||||||
|
self?.navigationController?.navigationBar.barTintColor = nil
|
||||||
|
self?.contentViewController.view.layer.cornerRadius = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
self.navigationBarAnimator?.startAnimation()
|
||||||
|
self.navigationBarAnimator?.pauseAnimation()
|
||||||
|
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
|
||||||
|
func resetNavigationBarAnimation()
|
||||||
|
{
|
||||||
|
self.navigationBarAnimator?.stopAnimation(true)
|
||||||
|
self.navigationBarAnimator = nil
|
||||||
|
|
||||||
|
self.hideNavigationBar()
|
||||||
|
self.navigationController?.navigationBar.barTintColor = .white
|
||||||
|
self.contentViewController.view.layer.cornerRadius = self.contentViewControllerShadowView.layer.cornerRadius
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
extension AppViewController
|
extension AppViewController
|
||||||
@@ -391,7 +478,7 @@ private extension AppViewController
|
|||||||
{
|
{
|
||||||
guard let navigationController = self.navigationController, navigationController.topViewController == self else { return }
|
guard let navigationController = self.navigationController, navigationController.topViewController == self else { return }
|
||||||
|
|
||||||
self._isEnteringForeground = true
|
self._shouldResetLayout = true
|
||||||
self.view.setNeedsLayout()
|
self.view.setNeedsLayout()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -185,6 +185,25 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" fixedFrame="YES" spacing="8" translatesAutoresizingMaskIntoConstraints="NO" id="Bql-t3-Ndi">
|
||||||
|
<rect key="frame" x="47" y="238" width="85" height="35"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<subviews>
|
||||||
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="j1W-Jn-HFI" customClass="AppIconImageView" customModule="AltStore" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="35" height="35"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="width" constant="35" id="aMS-N7-WYn"/>
|
||||||
|
<constraint firstAttribute="height" constant="35" id="psb-Ro-Js4"/>
|
||||||
|
</constraints>
|
||||||
|
</imageView>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Delta" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DTD-1Y-76c">
|
||||||
|
<rect key="frame" x="43" y="0.0" width="42" height="35"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CUB-SN-zdM">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="CUB-SN-zdM">
|
||||||
<rect key="frame" x="67" y="113" width="240" height="128"/>
|
<rect key="frame" x="67" y="113" width="240" height="128"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
@@ -217,7 +236,7 @@
|
|||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" alignment="center" spacing="11" translatesAutoresizingMaskIntoConstraints="NO" id="LZw-eU-5SO" userLabel="App Info">
|
<stackView opaque="NO" contentMode="scaleToFill" fixedFrame="YES" insetsLayoutMarginsFromSafeArea="NO" alignment="center" spacing="11" translatesAutoresizingMaskIntoConstraints="NO" id="LZw-eU-5SO" userLabel="App Info">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="270" height="93"/>
|
<rect key="frame" x="0.0" y="0.0" width="273" height="93"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3Ey-6S-HJx" customClass="AppIconImageView" customModule="AltStore" customModuleProvider="target">
|
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="3Ey-6S-HJx" customClass="AppIconImageView" customModule="AltStore" customModuleProvider="target">
|
||||||
@@ -228,16 +247,16 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
</imageView>
|
</imageView>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="100" insetsLayoutMarginsFromSafeArea="NO" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="bR7-SO-m8f">
|
<stackView opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="100" insetsLayoutMarginsFromSafeArea="NO" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="bR7-SO-m8f">
|
||||||
<rect key="frame" x="90" y="26.5" width="85" height="40.5"/>
|
<rect key="frame" x="90" y="26.5" width="88" height="40.5"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="100" verticalHuggingPriority="251" text="App Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dNE-IO-y3o">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="100" verticalHuggingPriority="251" text="App Name" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dNE-IO-y3o">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="85" height="21.5"/>
|
<rect key="frame" x="0.0" y="0.0" width="88" height="21.5"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="18"/>
|
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="100" verticalHuggingPriority="251" text="Developer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NKT-el-rRF">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="100" verticalHuggingPriority="251" text="Developer" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NKT-el-rRF">
|
||||||
<rect key="frame" x="0.0" y="23.5" width="85" height="17"/>
|
<rect key="frame" x="0.0" y="23.5" width="88" height="17"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="textColor" white="0.66666666669999997" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
@@ -245,7 +264,7 @@
|
|||||||
</subviews>
|
</subviews>
|
||||||
</stackView>
|
</stackView>
|
||||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mgB-Gs-bik" customClass="PillButton" customModule="AltStore" customModuleProvider="target">
|
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mgB-Gs-bik" customClass="PillButton" customModule="AltStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="186" y="31" width="72" height="31"/>
|
<rect key="frame" x="189" y="31" width="72" height="31"/>
|
||||||
<color key="backgroundColor" red="0.22352941179999999" green="0.4941176471" blue="0.39607843139999999" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
|
<color key="backgroundColor" red="0.22352941179999999" green="0.4941176471" blue="0.39607843139999999" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstAttribute="width" constant="72" id="j44-T1-0dc"/>
|
<constraint firstAttribute="width" constant="72" id="j44-T1-0dc"/>
|
||||||
@@ -272,16 +291,16 @@
|
|||||||
</connections>
|
</connections>
|
||||||
</containerView>
|
</containerView>
|
||||||
<visualEffectView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tUK-0J-07U">
|
<visualEffectView opaque="NO" clipsSubviews="YES" contentMode="scaleToFill" fixedFrame="YES" translatesAutoresizingMaskIntoConstraints="NO" id="tUK-0J-07U">
|
||||||
<rect key="frame" x="58" y="117" width="58" height="32"/>
|
<rect key="frame" x="58" y="117" width="18" height="18"/>
|
||||||
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" id="yyn-wP-xk4">
|
<view key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" ambiguous="YES" insetsLayoutMarginsFromSafeArea="NO" id="yyn-wP-xk4">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="58" height="32"/>
|
<rect key="frame" x="0.0" y="0.0" width="18" height="18"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mkD-3C-WMV">
|
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="mkD-3C-WMV">
|
||||||
<rect key="frame" x="3" y="7" width="52" height="18"/>
|
<rect key="frame" x="0.0" y="0.0" width="18" height="18"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" flexibleMinY="YES" heightSizable="YES" flexibleMaxY="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<state key="normal" title="Back" image="Back"/>
|
<state key="normal" image="Back"/>
|
||||||
<connections>
|
<connections>
|
||||||
<action selector="popViewController:" destination="0V6-N4-hTO" eventType="primaryActionTriggered" id="F6Z-xz-qCk"/>
|
<action selector="popViewController:" destination="0V6-N4-hTO" eventType="primaryActionTriggered" id="F6Z-xz-qCk"/>
|
||||||
</connections>
|
</connections>
|
||||||
@@ -306,7 +325,24 @@
|
|||||||
</constraints>
|
</constraints>
|
||||||
<viewLayoutGuide key="safeArea" id="wiR-52-nwg"/>
|
<viewLayoutGuide key="safeArea" id="wiR-52-nwg"/>
|
||||||
</view>
|
</view>
|
||||||
<navigationItem key="navigationItem" largeTitleDisplayMode="never" id="maq-gT-QcS"/>
|
<navigationItem key="navigationItem" largeTitleDisplayMode="never" id="maq-gT-QcS">
|
||||||
|
<barButtonItem key="rightBarButtonItem" style="plain" id="FLf-DS-F77">
|
||||||
|
<button key="customView" opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" id="grk-xM-YWA" customClass="PillButton" customModule="AltStore" customModuleProvider="target">
|
||||||
|
<rect key="frame" x="287" y="6.5" width="72" height="31"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
|
||||||
|
<color key="backgroundColor" red="0.22352941179999999" green="0.4941176471" blue="0.39607843139999999" alpha="0.10000000000000001" colorSpace="custom" customColorSpace="sRGB"/>
|
||||||
|
<constraints>
|
||||||
|
<constraint firstAttribute="height" constant="31" id="S2r-fI-PQB"/>
|
||||||
|
<constraint firstAttribute="width" constant="72" id="Xtq-UG-h3b"/>
|
||||||
|
</constraints>
|
||||||
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="14"/>
|
||||||
|
<state key="normal" title="FREE"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="performAppAction:" destination="0V6-N4-hTO" eventType="primaryActionTriggered" id="b2l-CA-mbO"/>
|
||||||
|
</connections>
|
||||||
|
</button>
|
||||||
|
</barButtonItem>
|
||||||
|
</navigationItem>
|
||||||
<connections>
|
<connections>
|
||||||
<outlet property="appIconImageView" destination="3Ey-6S-HJx" id="5FB-mn-E29"/>
|
<outlet property="appIconImageView" destination="3Ey-6S-HJx" id="5FB-mn-E29"/>
|
||||||
<outlet property="backButton" destination="mkD-3C-WMV" id="3m8-P7-yvT"/>
|
<outlet property="backButton" destination="mkD-3C-WMV" id="3m8-P7-yvT"/>
|
||||||
@@ -319,6 +355,10 @@
|
|||||||
<outlet property="headerContentView" destination="LZw-eU-5SO" id="hk1-xG-2kJ"/>
|
<outlet property="headerContentView" destination="LZw-eU-5SO" id="hk1-xG-2kJ"/>
|
||||||
<outlet property="headerView" destination="mgO-eN-SxQ" id="iIi-D7-XRt"/>
|
<outlet property="headerView" destination="mgO-eN-SxQ" id="iIi-D7-XRt"/>
|
||||||
<outlet property="nameLabel" destination="dNE-IO-y3o" id="tp1-IT-ByH"/>
|
<outlet property="nameLabel" destination="dNE-IO-y3o" id="tp1-IT-ByH"/>
|
||||||
|
<outlet property="navigationBarAppIconImageView" destination="j1W-Jn-HFI" id="2YU-ka-w9R"/>
|
||||||
|
<outlet property="navigationBarAppNameLabel" destination="DTD-1Y-76c" id="z9z-pp-dC4"/>
|
||||||
|
<outlet property="navigationBarDownloadButton" destination="grk-xM-YWA" id="Yrg-S0-tIM"/>
|
||||||
|
<outlet property="navigationBarTitleView" destination="Bql-t3-Ndi" id="aY1-Mt-1rl"/>
|
||||||
<outlet property="scrollView" destination="Ci9-Iw-aR2" id="6XJ-gn-ByV"/>
|
<outlet property="scrollView" destination="Ci9-Iw-aR2" id="6XJ-gn-ByV"/>
|
||||||
</connections>
|
</connections>
|
||||||
</viewController>
|
</viewController>
|
||||||
@@ -330,7 +370,7 @@
|
|||||||
<scene sceneID="CgX-7h-sRI">
|
<scene sceneID="CgX-7h-sRI">
|
||||||
<objects>
|
<objects>
|
||||||
<tableViewController id="kBq-V8-3XC" customClass="AppContentViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
<tableViewController id="kBq-V8-3XC" customClass="AppContentViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="w5c-Q3-FcU">
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" contentInsetAdjustmentBehavior="never" dataMode="static" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" contentViewInsetsToSafeArea="NO" id="w5c-Q3-FcU">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
@@ -346,7 +386,7 @@
|
|||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Classic games in your pocket" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BsL-O2-UjD">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Classic games in your pocket" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="BsL-O2-UjD">
|
||||||
<rect key="frame" x="20" y="20" width="335" height="17.5"/>
|
<rect key="frame" x="20" y="20" width="335" height="17.5"/>
|
||||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="14"/>
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
<nil key="textColor"/>
|
<nil key="textColor"/>
|
||||||
<nil key="highlightedColor"/>
|
<nil key="highlightedColor"/>
|
||||||
</label>
|
</label>
|
||||||
@@ -400,12 +440,12 @@
|
|||||||
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="EL5-UC-RIw" customClass="AppContentTableViewCell" customModule="AltStore" customModuleProvider="target">
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="none" indentationWidth="10" id="EL5-UC-RIw" customClass="AppContentTableViewCell" customModule="AltStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="0.0" y="101" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="101" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EL5-UC-RIw" id="D1G-nK-G0Z">
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" ambiguous="YES" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="EL5-UC-RIw" id="D1G-nK-G0Z">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Hello Me" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Pyt-8D-BZA" customClass="CollapsingTextView" customModule="AltStore" customModuleProvider="target">
|
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" text="Hello Me" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="Pyt-8D-BZA" customClass="CollapsingTextView" customModule="AltStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="20" y="20" width="335" height="4"/>
|
<rect key="frame" x="20" y="20" width="335" height="34"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
@@ -413,7 +453,7 @@
|
|||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
<constraint firstItem="Pyt-8D-BZA" firstAttribute="top" secondItem="D1G-nK-G0Z" secondAttribute="top" constant="20" id="Lm9-lx-kJ8"/>
|
<constraint firstItem="Pyt-8D-BZA" firstAttribute="top" secondItem="D1G-nK-G0Z" secondAttribute="top" constant="20" id="Lm9-lx-kJ8"/>
|
||||||
<constraint firstAttribute="bottom" secondItem="Pyt-8D-BZA" secondAttribute="bottom" constant="20" id="TSS-Au-gYx"/>
|
<constraint firstAttribute="bottom" secondItem="Pyt-8D-BZA" secondAttribute="bottom" constant="44" id="TSS-Au-gYx"/>
|
||||||
<constraint firstItem="Pyt-8D-BZA" firstAttribute="leading" secondItem="D1G-nK-G0Z" secondAttribute="leading" constant="20" id="UlS-ct-L9Y"/>
|
<constraint firstItem="Pyt-8D-BZA" firstAttribute="leading" secondItem="D1G-nK-G0Z" secondAttribute="leading" constant="20" id="UlS-ct-L9Y"/>
|
||||||
<constraint firstAttribute="trailing" secondItem="Pyt-8D-BZA" secondAttribute="trailing" constant="20" id="Wq4-Ql-wvN"/>
|
<constraint firstAttribute="trailing" secondItem="Pyt-8D-BZA" secondAttribute="trailing" constant="20" id="Wq4-Ql-wvN"/>
|
||||||
</constraints>
|
</constraints>
|
||||||
@@ -427,23 +467,56 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" spacing="11" translatesAutoresizingMaskIntoConstraints="NO" id="n9R-39-Glq">
|
<stackView opaque="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" axis="vertical" distribution="equalSpacing" spacing="12" translatesAutoresizingMaskIntoConstraints="NO" id="n9R-39-Glq">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="44"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="60"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="What's New" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="obM-TM-y2E">
|
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="4" translatesAutoresizingMaskIntoConstraints="NO" id="y3w-4S-e64">
|
||||||
<rect key="frame" x="20" y="0.0" width="335" height="13"/>
|
<rect key="frame" x="20" y="0.0" width="335" height="4"/>
|
||||||
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
|
<subviews>
|
||||||
<nil key="textColor"/>
|
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" spacing="11" translatesAutoresizingMaskIntoConstraints="NO" id="PFD-gZ-77F">
|
||||||
<nil key="highlightedColor"/>
|
<rect key="frame" x="0.0" y="0.0" width="335" height="0.0"/>
|
||||||
</label>
|
<subviews>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="What's New" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="obM-TM-y2E">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="123.5" height="0.0"/>
|
||||||
|
<fontDescription key="fontDescription" type="boldSystem" pointSize="22"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="2w ago" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="wGD-mS-8fO">
|
||||||
|
<rect key="frame" x="285" y="0.0" width="50" height="0.0"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
|
<color key="textColor" white="0.5" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
|
<stackView opaque="NO" contentMode="scaleToFill" distribution="equalSpacing" translatesAutoresizingMaskIntoConstraints="NO" id="ewH-gi-pyW">
|
||||||
|
<rect key="frame" x="0.0" y="4" width="335" height="0.0"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Version 4.4.2" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="7E0-TV-G4l">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="84.5" height="0.0"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="50.4 MB" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="DgM-bD-bBY">
|
||||||
|
<rect key="frame" x="280.5" y="0.0" width="54.5" height="0.0"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
||||||
|
<color key="textColor" white="0.66666666666666663" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
|
</subviews>
|
||||||
|
</stackView>
|
||||||
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="wQF-WY-Gdz" customClass="CollapsingTextView" customModule="AltStore" customModuleProvider="target">
|
<textView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" scrollEnabled="NO" editable="NO" textAlignment="natural" translatesAutoresizingMaskIntoConstraints="NO" id="wQF-WY-Gdz" customClass="CollapsingTextView" customModule="AltStore" customModuleProvider="target">
|
||||||
<rect key="frame" x="20" y="24" width="335" height="0.0"/>
|
<rect key="frame" x="20" y="16" width="335" height="0.0"/>
|
||||||
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
<fontDescription key="fontDescription" type="system" pointSize="15"/>
|
||||||
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
<textInputTraits key="textInputTraits" autocapitalizationType="sentences"/>
|
||||||
</textView>
|
</textView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<edgeInsets key="layoutMargins" top="0.0" left="20" bottom="20" right="20"/>
|
<edgeInsets key="layoutMargins" top="0.0" left="20" bottom="44" right="20"/>
|
||||||
</stackView>
|
</stackView>
|
||||||
</subviews>
|
</subviews>
|
||||||
<constraints>
|
<constraints>
|
||||||
@@ -462,7 +535,7 @@
|
|||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="149"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="149"/>
|
||||||
<autoresizingMask key="autoresizingMask"/>
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="center" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="Jvb-r8-XrY">
|
<stackView opaque="NO" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" axis="vertical" distribution="equalSpacing" alignment="center" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="Jvb-r8-XrY">
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="149"/>
|
<rect key="frame" x="0.0" y="0.0" width="375" height="149"/>
|
||||||
<subviews>
|
<subviews>
|
||||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Permissions" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dj7-G8-GFv">
|
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="751" text="Permissions" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="dj7-G8-GFv">
|
||||||
@@ -559,8 +632,11 @@ World</string>
|
|||||||
<outlet property="descriptionTextView" destination="Pyt-8D-BZA" id="cgV-Hg-LrH"/>
|
<outlet property="descriptionTextView" destination="Pyt-8D-BZA" id="cgV-Hg-LrH"/>
|
||||||
<outlet property="permissionsCollectionView" destination="r8T-dj-wQX" id="Xud-5X-w2E"/>
|
<outlet property="permissionsCollectionView" destination="r8T-dj-wQX" id="Xud-5X-w2E"/>
|
||||||
<outlet property="screenshotsCollectionView" destination="ppk-lL-at8" id="YoQ-Z6-WTP"/>
|
<outlet property="screenshotsCollectionView" destination="ppk-lL-at8" id="YoQ-Z6-WTP"/>
|
||||||
|
<outlet property="sizeLabel" destination="DgM-bD-bBY" id="Oky-ax-u20"/>
|
||||||
<outlet property="subtitleLabel" destination="BsL-O2-UjD" id="cfe-cf-4a9"/>
|
<outlet property="subtitleLabel" destination="BsL-O2-UjD" id="cfe-cf-4a9"/>
|
||||||
|
<outlet property="versionDateLabel" destination="wGD-mS-8fO" id="icB-lC-g9x"/>
|
||||||
<outlet property="versionDescriptionTextView" destination="wQF-WY-Gdz" id="rdV-rY-VAz"/>
|
<outlet property="versionDescriptionTextView" destination="wQF-WY-Gdz" id="rdV-rY-VAz"/>
|
||||||
|
<outlet property="versionLabel" destination="7E0-TV-G4l" id="Vb4-SR-E2o"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tableViewController>
|
</tableViewController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="dhh-ZN-LoG" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="dhh-ZN-LoG" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
@@ -950,7 +1026,7 @@ World</string>
|
|||||||
</namedColor>
|
</namedColor>
|
||||||
</resources>
|
</resources>
|
||||||
<inferredMetricsTieBreakers>
|
<inferredMetricsTieBreakers>
|
||||||
<segue reference="cnd-KK-o60"/>
|
<segue reference="gjN-bg-1G5"/>
|
||||||
</inferredMetricsTieBreakers>
|
</inferredMetricsTieBreakers>
|
||||||
<color key="tintColor" name="Green"/>
|
<color key="tintColor" name="Green"/>
|
||||||
</document>
|
</document>
|
||||||
|
|||||||
@@ -31,4 +31,16 @@ class NavigationBar: UINavigationBar
|
|||||||
self.barTintColor = .white
|
self.barTintColor = .white
|
||||||
self.shadowImage = UIImage()
|
self.shadowImage = UIImage()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override func layoutSubviews()
|
||||||
|
{
|
||||||
|
super.layoutSubviews()
|
||||||
|
|
||||||
|
// We can't easily shift just the back button up, so we shift the entire content view slightly.
|
||||||
|
for contentView in self.subviews
|
||||||
|
{
|
||||||
|
guard NSStringFromClass(type(of: contentView)).contains("ContentView") else { continue }
|
||||||
|
contentView.center.y -= 2
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
34
AltStore/Extensions/Date+RelativeDate.swift
Normal file
34
AltStore/Extensions/Date+RelativeDate.swift
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
//
|
||||||
|
// Date+RelativeDate.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 7/28/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension Date
|
||||||
|
{
|
||||||
|
func numberOfCalendarDays(since date: Date) -> Int
|
||||||
|
{
|
||||||
|
let today = Calendar.current.startOfDay(for: self)
|
||||||
|
let previousDay = Calendar.current.startOfDay(for: date)
|
||||||
|
|
||||||
|
let components = Calendar.current.dateComponents([.day], from: previousDay, to: today)
|
||||||
|
return components.day!
|
||||||
|
}
|
||||||
|
|
||||||
|
func relativeDateString(since date: Date, dateFormatter: DateFormatter) -> String
|
||||||
|
{
|
||||||
|
let numberOfDays = self.numberOfCalendarDays(since: date)
|
||||||
|
|
||||||
|
switch numberOfDays
|
||||||
|
{
|
||||||
|
case 0: return NSLocalizedString("Today", comment: "")
|
||||||
|
case 1: return NSLocalizedString("Yesterday", comment: "")
|
||||||
|
case 2...7: return String(format: NSLocalizedString("%@ days ago", comment: ""), NSNumber(value: numberOfDays))
|
||||||
|
default: return dateFormatter.string(from: date)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -25,18 +25,6 @@ extension MyAppsViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Date
|
|
||||||
{
|
|
||||||
func numberOfCalendarDays(since date: Date) -> Int
|
|
||||||
{
|
|
||||||
let today = Calendar.current.startOfDay(for: self)
|
|
||||||
let previousDay = Calendar.current.startOfDay(for: date)
|
|
||||||
|
|
||||||
let components = Calendar.current.dateComponents([.day], from: previousDay, to: today)
|
|
||||||
return components.day!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyAppsViewController: UICollectionViewController
|
class MyAppsViewController: UICollectionViewController
|
||||||
{
|
{
|
||||||
private lazy var dataSource = self.makeDataSource()
|
private lazy var dataSource = self.makeDataSource()
|
||||||
@@ -190,16 +178,7 @@ private extension MyAppsViewController
|
|||||||
let progress = AppManager.shared.installationProgress(for: app)
|
let progress = AppManager.shared.installationProgress(for: app)
|
||||||
cell.updateButton.progress = progress
|
cell.updateButton.progress = progress
|
||||||
|
|
||||||
cell.dateLabel.text = self.dateFormatter.string(from: app.versionDate)
|
cell.dateLabel.text = Date().relativeDateString(since: app.versionDate, dateFormatter: self.dateFormatter)
|
||||||
|
|
||||||
let numberOfDays = Date().numberOfCalendarDays(since: app.versionDate)
|
|
||||||
switch numberOfDays
|
|
||||||
{
|
|
||||||
case 0: cell.dateLabel.text = NSLocalizedString("Today", comment: "")
|
|
||||||
case 1: cell.dateLabel.text = NSLocalizedString("Yesterday", comment: "")
|
|
||||||
case 2...7: cell.dateLabel.text = String(format: NSLocalizedString("%@ days ago", comment: ""), NSNumber(value: numberOfDays))
|
|
||||||
default: cell.dateLabel.text = self.dateFormatter.string(from: app.versionDate)
|
|
||||||
}
|
|
||||||
|
|
||||||
cell.setNeedsLayout()
|
cell.setNeedsLayout()
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user