mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-11 15:53:30 +01:00
Displays remaining App ID count
This commit is contained in:
@@ -1,9 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15400" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="wKh-xq-NuP">
|
||||
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="15705" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="wKh-xq-NuP">
|
||||
<device id="retina4_7" orientation="portrait" appearance="light"/>
|
||||
<dependencies>
|
||||
<deployment identifier="iOS"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15404"/>
|
||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="15706"/>
|
||||
<capability name="Named colors" minToolsVersion="9.0"/>
|
||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||
@@ -629,7 +629,7 @@ World</string>
|
||||
<collectionViewFlowLayout key="collectionViewLayout" minimumLineSpacing="15" minimumInteritemSpacing="10" id="SB5-U0-jyy">
|
||||
<size key="itemSize" width="375" height="60"/>
|
||||
<size key="headerReferenceSize" width="50" height="50"/>
|
||||
<size key="footerReferenceSize" width="0.0" height="0.0"/>
|
||||
<size key="footerReferenceSize" width="50" height="50"/>
|
||||
<inset key="sectionInset" minX="0.0" minY="0.0" maxX="0.0" maxY="0.0"/>
|
||||
</collectionViewFlowLayout>
|
||||
<cells>
|
||||
@@ -750,6 +750,39 @@ World</string>
|
||||
<outlet property="textLabel" destination="BDU-hM-rro" id="CQM-8K-bcH"/>
|
||||
</connections>
|
||||
</collectionReusableView>
|
||||
<collectionReusableView key="sectionFooterView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" insetsLayoutMarginsFromSafeArea="NO" reuseIdentifier="InstalledAppsFooter" id="HYs-co-nJZ" customClass="InstalledAppsCollectionFooterView" customModule="AltStore" customModuleProvider="target">
|
||||
<rect key="frame" x="0.0" y="185" width="375" height="50"/>
|
||||
<autoresizingMask key="autoresizingMask"/>
|
||||
<subviews>
|
||||
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="5/10 App IDs" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="LLv-8I-6Of">
|
||||
<rect key="frame" x="138.5" y="0.0" width="98" height="21"/>
|
||||
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||
<color key="textColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
|
||||
<nil key="highlightedColor"/>
|
||||
</label>
|
||||
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="NHb-0F-cHZ">
|
||||
<rect key="frame" x="241.5" y="-0.5" width="22" height="22"/>
|
||||
<constraints>
|
||||
<constraint firstAttribute="width" constant="22" id="K1V-bV-Mjg"/>
|
||||
<constraint firstAttribute="height" constant="22" id="vW1-aN-slG"/>
|
||||
</constraints>
|
||||
<state key="normal" image="questionmark.circle" catalog="system"/>
|
||||
<connections>
|
||||
<action selector="presentAppIDHelpAlert:" destination="hv7-Ar-voT" eventType="touchUpInside" id="m2N-Lx-adY"/>
|
||||
</connections>
|
||||
</button>
|
||||
</subviews>
|
||||
<constraints>
|
||||
<constraint firstItem="NHb-0F-cHZ" firstAttribute="leading" secondItem="LLv-8I-6Of" secondAttribute="trailing" constant="5" id="Fpk-zD-6AK"/>
|
||||
<constraint firstItem="LLv-8I-6Of" firstAttribute="top" secondItem="HYs-co-nJZ" secondAttribute="top" id="UVG-MJ-SPb"/>
|
||||
<constraint firstItem="LLv-8I-6Of" firstAttribute="centerX" secondItem="HYs-co-nJZ" secondAttribute="centerX" id="Wc0-ul-McA"/>
|
||||
<constraint firstItem="NHb-0F-cHZ" firstAttribute="centerY" secondItem="LLv-8I-6Of" secondAttribute="centerY" id="wSf-Lv-NC0"/>
|
||||
</constraints>
|
||||
<connections>
|
||||
<outlet property="button" destination="NHb-0F-cHZ" id="wOh-Ee-jhN"/>
|
||||
<outlet property="textLabel" destination="LLv-8I-6Of" id="t2D-f1-5pC"/>
|
||||
</connections>
|
||||
</collectionReusableView>
|
||||
<connections>
|
||||
<outlet property="dataSource" destination="hv7-Ar-voT" id="YOx-f4-chF"/>
|
||||
<outlet property="delegate" destination="hv7-Ar-voT" id="1PN-pf-cZK"/>
|
||||
@@ -797,6 +830,7 @@ World</string>
|
||||
<image name="MyApps" width="20" height="20"/>
|
||||
<image name="News" width="19" height="20"/>
|
||||
<image name="Settings" width="20" height="20"/>
|
||||
<image name="questionmark.circle" catalog="system" width="64" height="60"/>
|
||||
<namedColor name="Background">
|
||||
<color red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
||||
</namedColor>
|
||||
|
||||
@@ -30,6 +30,12 @@ class InstalledAppsCollectionHeaderView: UICollectionReusableView
|
||||
@IBOutlet var button: UIButton!
|
||||
}
|
||||
|
||||
class InstalledAppsCollectionFooterView: UICollectionReusableView
|
||||
{
|
||||
@IBOutlet var textLabel: UILabel!
|
||||
@IBOutlet var button: UIButton!
|
||||
}
|
||||
|
||||
class NoUpdatesCollectionViewCell: UICollectionViewCell
|
||||
{
|
||||
@IBOutlet var blurView: UIVisualEffectView!
|
||||
|
||||
@@ -615,7 +615,7 @@ private extension MyAppsViewController
|
||||
|
||||
func presentSideloadingAlert(completion: @escaping (Bool) -> Void)
|
||||
{
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Sideload Apps (Beta)", comment: ""), message: NSLocalizedString("You may only install 10 apps + app extensions per week due to Apple's restrictions.\n\nIf you encounter an app that is not able to be sideloaded, please report the app to support@altstore.io.", comment: ""), preferredStyle: .alert)
|
||||
let alertController = UIAlertController(title: NSLocalizedString("Sideload Apps (Beta)", comment: ""), message: NSLocalizedString("If you encounter an app that is not able to be sideloaded, please report the app to support@altstore.io.", comment: ""), preferredStyle: .alert)
|
||||
alertController.addAction(UIAlertAction(title: RSTSystemLocalizedString("OK"), style: .default, handler: { (action) in
|
||||
completion(true)
|
||||
}))
|
||||
@@ -700,6 +700,19 @@ private extension MyAppsViewController
|
||||
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
|
||||
@IBAction func presentAppIDHelpAlert(_ sender: UIButton)
|
||||
{
|
||||
let message = NSLocalizedString("""
|
||||
Each app and app extension installed with AltStore must register an App ID with Apple. Apple limits free developer accounts to 10 App IDs at a time.
|
||||
|
||||
App IDs expire after one week, but AltStore will automatically renew them for all installed apps. Once an App ID expires, it no longer counts toward your total.
|
||||
""", comment: "")
|
||||
|
||||
let alertController = UIAlertController(title: NSLocalizedString("What are App IDs?", comment: ""), message: message, preferredStyle: .alert)
|
||||
alertController.addAction(.ok)
|
||||
self.present(alertController, animated: true, completion: nil)
|
||||
}
|
||||
}
|
||||
|
||||
private extension MyAppsViewController
|
||||
@@ -805,7 +818,7 @@ extension MyAppsViewController
|
||||
|
||||
return headerView
|
||||
|
||||
case .installedApps:
|
||||
case .installedApps where kind == UICollectionView.elementKindSectionHeader:
|
||||
let headerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "InstalledAppsHeader", for: indexPath) as! InstalledAppsCollectionHeaderView
|
||||
|
||||
UIView.performWithoutAnimation {
|
||||
@@ -821,6 +834,29 @@ extension MyAppsViewController
|
||||
}
|
||||
|
||||
return headerView
|
||||
|
||||
case .installedApps:
|
||||
let installedApps = self.installedAppsDataSource.fetchedResultsController.fetchedObjects ?? []
|
||||
let registeredAppIDs = installedApps.filter { $0.team?.isActiveTeam ?? false }.reduce(0) { (sum, installedApp) in
|
||||
// Each InstallApp has it's own app ID, plus one for each app extension.
|
||||
return sum + 1 + installedApp.appExtensions.count
|
||||
}
|
||||
|
||||
let maximumAppIDCount = 10
|
||||
let remainingAppIDs = max(maximumAppIDCount - registeredAppIDs, 0)
|
||||
|
||||
let footerView = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionFooter, withReuseIdentifier: "InstalledAppsFooter", for: indexPath) as! InstalledAppsCollectionFooterView
|
||||
|
||||
if remainingAppIDs == 1
|
||||
{
|
||||
footerView.textLabel.text = String(format: NSLocalizedString("1 App ID Remaining", comment: ""))
|
||||
}
|
||||
else
|
||||
{
|
||||
footerView.textLabel.text = String(format: NSLocalizedString("%@ App IDs Remaining", comment: ""), NSNumber(value: remainingAppIDs))
|
||||
}
|
||||
|
||||
return footerView
|
||||
}
|
||||
}
|
||||
|
||||
@@ -889,6 +925,29 @@ extension MyAppsViewController: UICollectionViewDelegateFlowLayout
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForFooterInSection section: Int) -> CGSize
|
||||
{
|
||||
let section = Section.allCases[section]
|
||||
switch section
|
||||
{
|
||||
case .noUpdates: return .zero
|
||||
case .updates: return .zero
|
||||
case .installedApps:
|
||||
#if BETA
|
||||
if let team = DatabaseManager.shared.activeTeam(), team.type == .free
|
||||
{
|
||||
return CGSize(width: collectionView.bounds.width, height: 44)
|
||||
}
|
||||
else
|
||||
{
|
||||
return .zero
|
||||
}
|
||||
#else
|
||||
return .zero
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
func collectionView(_ myCV: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets
|
||||
{
|
||||
let section = Section.allCases[section]
|
||||
|
||||
@@ -164,6 +164,12 @@ class AuthenticationOperation: ResultOperation<(ALTSigner, ALTAppleAPISession)>
|
||||
team.isActiveTeam = false
|
||||
}
|
||||
|
||||
if let altStoreApp = InstalledApp.fetchAltStore(in: context), altStoreApp.team == nil
|
||||
{
|
||||
// No team assigned to AltStore app yet, so assume this team was used to originally install it.
|
||||
altStoreApp.team = team
|
||||
}
|
||||
|
||||
// Save
|
||||
try context.save()
|
||||
|
||||
|
||||
Reference in New Issue
Block a user