mirror of
https://github.com/SideStore/SideStore.git
synced 2026-02-09 06:43:25 +01:00
Adds basic MyAppsViewController implementation
This commit is contained in:
@@ -14,9 +14,10 @@
|
|||||||
BFB1169D22932DB100BB457C /* Apps.json in Resources */ = {isa = PBXBuildFile; fileRef = BFB1169C22932DB100BB457C /* Apps.json */; };
|
BFB1169D22932DB100BB457C /* Apps.json in Resources */ = {isa = PBXBuildFile; fileRef = BFB1169C22932DB100BB457C /* Apps.json */; };
|
||||||
BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */; };
|
BFBBE2DD22931B20002097FA /* AltStore.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */; };
|
||||||
BFBBE2DF22931F73002097FA /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DE22931F73002097FA /* App.swift */; };
|
BFBBE2DF22931F73002097FA /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2DE22931F73002097FA /* App.swift */; };
|
||||||
|
BFBBE2E122931F81002097FA /* InstalledApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFBBE2E022931F81002097FA /* InstalledApp.swift */; };
|
||||||
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; };
|
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; };
|
||||||
BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476F2284B9A500981D42 /* AppsViewController.swift */; };
|
BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476F2284B9A500981D42 /* AppsViewController.swift */; };
|
||||||
BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247712284B9A500981D42 /* SecondViewController.swift */; };
|
BFD247722284B9A500981D42 /* MyAppsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247712284B9A500981D42 /* MyAppsViewController.swift */; };
|
||||||
BFD247752284B9A500981D42 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247732284B9A500981D42 /* Main.storyboard */; };
|
BFD247752284B9A500981D42 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247732284B9A500981D42 /* Main.storyboard */; };
|
||||||
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFD247762284B9A700981D42 /* Assets.xcassets */; };
|
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFD247762284B9A700981D42 /* Assets.xcassets */; };
|
||||||
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247782284B9A700981D42 /* LaunchScreen.storyboard */; };
|
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247782284B9A700981D42 /* LaunchScreen.storyboard */; };
|
||||||
@@ -51,10 +52,11 @@
|
|||||||
BFB1169C22932DB100BB457C /* Apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Apps.json; sourceTree = "<group>"; };
|
BFB1169C22932DB100BB457C /* Apps.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = Apps.json; sourceTree = "<group>"; };
|
||||||
BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = AltStore.xcdatamodel; sourceTree = "<group>"; };
|
BFBBE2DC22931B20002097FA /* AltStore.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = AltStore.xcdatamodel; sourceTree = "<group>"; };
|
||||||
BFBBE2DE22931F73002097FA /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
BFBBE2DE22931F73002097FA /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
|
||||||
|
BFBBE2E022931F81002097FA /* InstalledApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InstalledApp.swift; sourceTree = "<group>"; };
|
||||||
BFD2476A2284B9A500981D42 /* AltStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltStore.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
BFD2476A2284B9A500981D42 /* AltStore.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = AltStore.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
BFD2476D2284B9A500981D42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
BFD2476D2284B9A500981D42 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
BFD2476F2284B9A500981D42 /* AppsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsViewController.swift; sourceTree = "<group>"; };
|
BFD2476F2284B9A500981D42 /* AppsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppsViewController.swift; sourceTree = "<group>"; };
|
||||||
BFD247712284B9A500981D42 /* SecondViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SecondViewController.swift; sourceTree = "<group>"; };
|
BFD247712284B9A500981D42 /* MyAppsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MyAppsViewController.swift; sourceTree = "<group>"; };
|
||||||
BFD247742284B9A500981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
BFD247742284B9A500981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = "<group>"; };
|
||||||
BFD247762284B9A700981D42 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
BFD247762284B9A700981D42 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||||
BFD247792284B9A700981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
BFD247792284B9A700981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
@@ -80,6 +82,14 @@
|
|||||||
/* End PBXFrameworksBuildPhase section */
|
/* End PBXFrameworksBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXGroup section */
|
/* Begin PBXGroup section */
|
||||||
|
BFBBE2E2229320A2002097FA /* My Apps */ = {
|
||||||
|
isa = PBXGroup;
|
||||||
|
children = (
|
||||||
|
BFD247712284B9A500981D42 /* MyAppsViewController.swift */,
|
||||||
|
);
|
||||||
|
path = "My Apps";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
BFD247612284B9A500981D42 = {
|
BFD247612284B9A500981D42 = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
@@ -103,10 +113,10 @@
|
|||||||
BFD2476D2284B9A500981D42 /* AppDelegate.swift */,
|
BFD2476D2284B9A500981D42 /* AppDelegate.swift */,
|
||||||
BFD247732284B9A500981D42 /* Main.storyboard */,
|
BFD247732284B9A500981D42 /* Main.storyboard */,
|
||||||
BFD2478A2284C49000981D42 /* Apps */,
|
BFD2478A2284C49000981D42 /* Apps */,
|
||||||
|
BFBBE2E2229320A2002097FA /* My Apps */,
|
||||||
BFD247982284D7FC00981D42 /* Model */,
|
BFD247982284D7FC00981D42 /* Model */,
|
||||||
BFD2478D2284C4C700981D42 /* Components */,
|
BFD2478D2284C4C700981D42 /* Components */,
|
||||||
BFD2479D2284FBBD00981D42 /* Extensions */,
|
BFD2479D2284FBBD00981D42 /* Extensions */,
|
||||||
BFD247712284B9A500981D42 /* SecondViewController.swift */,
|
|
||||||
BFD247962284D7C100981D42 /* Resources */,
|
BFD247962284D7C100981D42 /* Resources */,
|
||||||
BFD247972284D7D800981D42 /* Supporting Files */,
|
BFD247972284D7D800981D42 /* Supporting Files */,
|
||||||
);
|
);
|
||||||
@@ -165,6 +175,7 @@
|
|||||||
BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */,
|
BFBBE2DB22931B20002097FA /* AltStore.xcdatamodeld */,
|
||||||
BFB11691229322E400BB457C /* DatabaseManager.swift */,
|
BFB11691229322E400BB457C /* DatabaseManager.swift */,
|
||||||
BFBBE2DE22931F73002097FA /* App.swift */,
|
BFBBE2DE22931F73002097FA /* App.swift */,
|
||||||
|
BFBBE2E022931F81002097FA /* InstalledApp.swift */,
|
||||||
);
|
);
|
||||||
path = Model;
|
path = Model;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -252,8 +263,9 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
|
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
|
||||||
BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */,
|
BFD247722284B9A500981D42 /* MyAppsViewController.swift in Sources */,
|
||||||
BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */,
|
BFB11692229322E400BB457C /* DatabaseManager.swift in Sources */,
|
||||||
|
BFBBE2E122931F81002097FA /* InstalledApp.swift in Sources */,
|
||||||
BFBBE2DF22931F73002097FA /* App.swift in Sources */,
|
BFBBE2DF22931F73002097FA /* App.swift in Sources */,
|
||||||
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */,
|
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */,
|
||||||
BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */,
|
BFD2479C2284E19A00981D42 /* AppDetailViewController.swift in Sources */,
|
||||||
|
|||||||
@@ -48,6 +48,8 @@ class AppDetailViewController: UITableViewController
|
|||||||
self.tableView.delegate = self
|
self.tableView.delegate = self
|
||||||
self.screenshotsCollectionView.dataSource = self.screenshotsDataSource
|
self.screenshotsCollectionView.dataSource = self.screenshotsDataSource
|
||||||
|
|
||||||
|
self.downloadButton.activityIndicatorView.style = .white
|
||||||
|
|
||||||
self.update()
|
self.update()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +97,39 @@ private extension AppDetailViewController
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private extension AppDetailViewController
|
||||||
|
{
|
||||||
|
@IBAction func downloadApp(_ sender: UIButton)
|
||||||
|
{
|
||||||
|
guard self.app.installedApp == nil else { return }
|
||||||
|
|
||||||
|
sender.isIndicatingActivity = true
|
||||||
|
|
||||||
|
DatabaseManager.shared.persistentContainer.performBackgroundTask { (context) in
|
||||||
|
let app = context.object(with: self.app.objectID) as! App
|
||||||
|
|
||||||
|
_ = InstalledApp(app: app,
|
||||||
|
bundleIdentifier: app.identifier,
|
||||||
|
signedDate: Date(),
|
||||||
|
expirationDate: Date().addingTimeInterval(60 * 60 * 24 * 7),
|
||||||
|
context: context)
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try context.save()
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
print("Failed to download app.", error)
|
||||||
|
}
|
||||||
|
|
||||||
|
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
|
||||||
|
sender.isIndicatingActivity = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
extension AppDetailViewController
|
extension AppDetailViewController
|
||||||
{
|
{
|
||||||
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
|
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
|
||||||
|
|||||||
@@ -59,6 +59,15 @@ private extension AppsViewController
|
|||||||
cell.developerLabel.text = app.developerName
|
cell.developerLabel.text = app.developerName
|
||||||
cell.appIconImageView.image = UIImage(named: app.iconName)
|
cell.appIconImageView.image = UIImage(named: app.iconName)
|
||||||
|
|
||||||
|
if app.installedApp != nil
|
||||||
|
{
|
||||||
|
cell.button.isEnabled = false
|
||||||
|
cell.button.setTitle(NSLocalizedString("Installed", comment: ""), for: .normal)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cell.button.isEnabled = true
|
||||||
|
cell.button.setTitle(NSLocalizedString("Download", comment: ""), for: .normal)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,47 +6,9 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<deployment identifier="iOS"/>
|
<deployment identifier="iOS"/>
|
||||||
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="14490.49"/>
|
||||||
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
|
|
||||||
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
<scenes>
|
<scenes>
|
||||||
<!--Second-->
|
|
||||||
<scene sceneID="wg7-f3-ORb">
|
|
||||||
<objects>
|
|
||||||
<viewController id="8rJ-Kc-sve" customClass="SecondViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
|
||||||
<view key="view" contentMode="scaleToFill" id="QS5-Rx-YEW">
|
|
||||||
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
|
||||||
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
|
||||||
<subviews>
|
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleToFill" text="Second View" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="zEq-FU-wV5">
|
|
||||||
<rect key="frame" x="87" y="312" width="201.5" height="43"/>
|
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="36"/>
|
|
||||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
<label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Loaded by SecondViewController" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="NDk-cv-Gan">
|
|
||||||
<rect key="frame" x="80" y="363" width="215" height="17"/>
|
|
||||||
<fontDescription key="fontDescription" type="system" pointSize="14"/>
|
|
||||||
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
|
|
||||||
<nil key="highlightedColor"/>
|
|
||||||
</label>
|
|
||||||
</subviews>
|
|
||||||
<color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
|
|
||||||
<constraints>
|
|
||||||
<constraint firstItem="NDk-cv-Gan" firstAttribute="top" secondItem="zEq-FU-wV5" secondAttribute="bottom" constant="8" symbolic="YES" id="Day-4N-Vmt"/>
|
|
||||||
<constraint firstItem="NDk-cv-Gan" firstAttribute="centerX" secondItem="zEq-FU-wV5" secondAttribute="centerX" id="JgO-Fn-dHn"/>
|
|
||||||
<constraint firstAttribute="centerX" secondItem="zEq-FU-wV5" secondAttribute="centerX" id="qqM-NS-xev"/>
|
|
||||||
<constraint firstAttribute="centerY" secondItem="zEq-FU-wV5" secondAttribute="centerY" id="qzY-Ky-pLD"/>
|
|
||||||
</constraints>
|
|
||||||
<viewLayoutGuide key="safeArea" id="O1u-W8-tvY"/>
|
|
||||||
</view>
|
|
||||||
<tabBarItem key="tabBarItem" title="Second" image="second" id="cPa-gy-q4n"/>
|
|
||||||
</viewController>
|
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="4Nw-L8-lE0" sceneMemberID="firstResponder"/>
|
|
||||||
</objects>
|
|
||||||
<point key="canvasLocation" x="750" y="360"/>
|
|
||||||
</scene>
|
|
||||||
<!--Tab Bar Controller-->
|
<!--Tab Bar Controller-->
|
||||||
<scene sceneID="yl2-sM-qoP">
|
<scene sceneID="yl2-sM-qoP">
|
||||||
<objects>
|
<objects>
|
||||||
@@ -58,13 +20,58 @@
|
|||||||
</tabBar>
|
</tabBar>
|
||||||
<connections>
|
<connections>
|
||||||
<segue destination="XF0-gk-CxQ" kind="relationship" relationship="viewControllers" id="uf8-vX-M3B"/>
|
<segue destination="XF0-gk-CxQ" kind="relationship" relationship="viewControllers" id="uf8-vX-M3B"/>
|
||||||
<segue destination="8rJ-Kc-sve" kind="relationship" relationship="viewControllers" id="0YU-bO-QiZ"/>
|
<segue destination="v8c-d9-T9x" kind="relationship" relationship="viewControllers" id="fqx-5p-YCD"/>
|
||||||
</connections>
|
</connections>
|
||||||
</tabBarController>
|
</tabBarController>
|
||||||
<placeholder placeholderIdentifier="IBFirstResponder" id="HuB-VB-40B" sceneMemberID="firstResponder"/>
|
<placeholder placeholderIdentifier="IBFirstResponder" id="HuB-VB-40B" sceneMemberID="firstResponder"/>
|
||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="0.0" y="0.0"/>
|
<point key="canvasLocation" x="0.0" y="0.0"/>
|
||||||
</scene>
|
</scene>
|
||||||
|
<!--My Apps-->
|
||||||
|
<scene sceneID="eRf-VD-MSX">
|
||||||
|
<objects>
|
||||||
|
<tableViewController id="Xf1-LZ-1vU" customClass="MyAppsViewController" customModule="AltStore" customModuleProvider="target" sceneMemberID="viewController">
|
||||||
|
<tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="prototypes" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="hkn-c3-iKp">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
|
||||||
|
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
|
||||||
|
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
|
||||||
|
<prototypes>
|
||||||
|
<tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" reuseIdentifier="Cell" textLabel="kY8-9c-qLE" detailTextLabel="XWn-JG-SYe" style="IBUITableViewCellStyleSubtitle" id="Lwi-IB-I9S">
|
||||||
|
<rect key="frame" x="0.0" y="28" width="375" height="44"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="Lwi-IB-I9S" id="4Vg-jI-f8V">
|
||||||
|
<rect key="frame" x="0.0" y="0.0" width="375" height="43.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<subviews>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Title" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="kY8-9c-qLE">
|
||||||
|
<rect key="frame" x="16" y="5" width="33.5" height="20.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="17"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Subtitle" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="XWn-JG-SYe">
|
||||||
|
<rect key="frame" x="16" y="25.5" width="44" height="14.5"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
<fontDescription key="fontDescription" type="system" pointSize="12"/>
|
||||||
|
<nil key="textColor"/>
|
||||||
|
<nil key="highlightedColor"/>
|
||||||
|
</label>
|
||||||
|
</subviews>
|
||||||
|
</tableViewCellContentView>
|
||||||
|
</tableViewCell>
|
||||||
|
</prototypes>
|
||||||
|
<connections>
|
||||||
|
<outlet property="dataSource" destination="Xf1-LZ-1vU" id="Lsq-Jy-ugM"/>
|
||||||
|
<outlet property="delegate" destination="Xf1-LZ-1vU" id="0YS-oa-D9d"/>
|
||||||
|
</connections>
|
||||||
|
</tableView>
|
||||||
|
<navigationItem key="navigationItem" title="My Apps" id="dz9-0e-LKa"/>
|
||||||
|
</tableViewController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="nb5-5T-hHT" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="1518" y="420"/>
|
||||||
|
</scene>
|
||||||
<!--Apps-->
|
<!--Apps-->
|
||||||
<scene sceneID="JlP-x7-lBT">
|
<scene sceneID="JlP-x7-lBT">
|
||||||
<objects>
|
<objects>
|
||||||
@@ -219,6 +226,9 @@
|
|||||||
<rect key="frame" x="0.0" y="129" width="343" height="34"/>
|
<rect key="frame" x="0.0" y="129" width="343" height="34"/>
|
||||||
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="18"/>
|
||||||
<state key="normal" title="Download"/>
|
<state key="normal" title="Download"/>
|
||||||
|
<connections>
|
||||||
|
<action selector="downloadApp:" destination="hR3-go-2DG" eventType="primaryActionTriggered" id="TZ5-aD-2Bp"/>
|
||||||
|
</connections>
|
||||||
</button>
|
</button>
|
||||||
</subviews>
|
</subviews>
|
||||||
</stackView>
|
</stackView>
|
||||||
@@ -376,6 +386,25 @@
|
|||||||
</objects>
|
</objects>
|
||||||
<point key="canvasLocation" x="749.60000000000002" y="-318.89055472263868"/>
|
<point key="canvasLocation" x="749.60000000000002" y="-318.89055472263868"/>
|
||||||
</scene>
|
</scene>
|
||||||
|
<!--My Apps-->
|
||||||
|
<scene sceneID="Edw-HT-TTT">
|
||||||
|
<objects>
|
||||||
|
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="v8c-d9-T9x" sceneMemberID="viewController">
|
||||||
|
<tabBarItem key="tabBarItem" title="My Apps" image="second" id="Pld-qe-pas"/>
|
||||||
|
<toolbarItems/>
|
||||||
|
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="PKd-0h-fii">
|
||||||
|
<rect key="frame" x="0.0" y="20" width="375" height="96"/>
|
||||||
|
<autoresizingMask key="autoresizingMask"/>
|
||||||
|
</navigationBar>
|
||||||
|
<nil name="viewControllers"/>
|
||||||
|
<connections>
|
||||||
|
<segue destination="Xf1-LZ-1vU" kind="relationship" relationship="rootViewController" id="uaQ-4h-SJu"/>
|
||||||
|
</connections>
|
||||||
|
</navigationController>
|
||||||
|
<placeholder placeholderIdentifier="IBFirstResponder" id="G7O-77-OQq" userLabel="First Responder" sceneMemberID="firstResponder"/>
|
||||||
|
</objects>
|
||||||
|
<point key="canvasLocation" x="749.60000000000002" y="420.53973013493254"/>
|
||||||
|
</scene>
|
||||||
</scenes>
|
</scenes>
|
||||||
<resources>
|
<resources>
|
||||||
<image name="DeltaIcon" width="512" height="512"/>
|
<image name="DeltaIcon" width="512" height="512"/>
|
||||||
|
|||||||
@@ -41,12 +41,25 @@ class Button: UIButton
|
|||||||
self.update()
|
self.update()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override var isEnabled: Bool {
|
||||||
|
didSet {
|
||||||
|
self.update()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private extension Button
|
private extension Button
|
||||||
{
|
{
|
||||||
func update()
|
func update()
|
||||||
{
|
{
|
||||||
self.backgroundColor = self.tintColor
|
if self.isEnabled
|
||||||
|
{
|
||||||
|
self.backgroundColor = self.tintColor
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self.backgroundColor = .lightGray
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,13 +7,22 @@
|
|||||||
<attribute name="localizedDescription" attributeType="String" syncable="YES"/>
|
<attribute name="localizedDescription" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="name" attributeType="String" syncable="YES"/>
|
<attribute name="name" attributeType="String" syncable="YES"/>
|
||||||
<attribute name="screenshotNames" attributeType="Transformable" syncable="YES"/>
|
<attribute name="screenshotNames" attributeType="Transformable" syncable="YES"/>
|
||||||
|
<relationship name="installedApp" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="InstalledApp" inverseName="app" inverseEntity="InstalledApp" syncable="YES"/>
|
||||||
<uniquenessConstraints>
|
<uniquenessConstraints>
|
||||||
<uniquenessConstraint>
|
<uniquenessConstraint>
|
||||||
<constraint value="identifier"/>
|
<constraint value="identifier"/>
|
||||||
</uniquenessConstraint>
|
</uniquenessConstraint>
|
||||||
</uniquenessConstraints>
|
</uniquenessConstraints>
|
||||||
</entity>
|
</entity>
|
||||||
|
<entity name="InstalledApp" representedClassName="InstalledApp" syncable="YES">
|
||||||
|
<attribute name="bundleIdentifier" attributeType="String" syncable="YES"/>
|
||||||
|
<attribute name="expirationDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||||
|
<attribute name="isBeta" attributeType="Boolean" defaultValueString="NO" usesScalarValueType="YES" syncable="YES"/>
|
||||||
|
<attribute name="signedDate" attributeType="Date" usesScalarValueType="NO" syncable="YES"/>
|
||||||
|
<relationship name="app" optional="YES" maxCount="1" deletionRule="Nullify" destinationEntity="App" inverseName="installedApp" inverseEntity="App" syncable="YES"/>
|
||||||
|
</entity>
|
||||||
<elements>
|
<elements>
|
||||||
<element name="App" positionX="-63" positionY="-18" width="128" height="135"/>
|
<element name="App" positionX="-63" positionY="-18" width="128" height="150"/>
|
||||||
|
<element name="InstalledApp" positionX="-63" positionY="0" width="128" height="120"/>
|
||||||
</elements>
|
</elements>
|
||||||
</model>
|
</model>
|
||||||
@@ -22,6 +22,9 @@ class App: NSManagedObject, Decodable
|
|||||||
@NSManaged private(set) var iconName: String
|
@NSManaged private(set) var iconName: String
|
||||||
@NSManaged private(set) var screenshotNames: [String]
|
@NSManaged private(set) var screenshotNames: [String]
|
||||||
|
|
||||||
|
/* Relationships */
|
||||||
|
@NSManaged private(set) var installedApp: InstalledApp?
|
||||||
|
|
||||||
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
||||||
{
|
{
|
||||||
super.init(entity: entity, insertInto: context)
|
super.init(entity: entity, insertInto: context)
|
||||||
|
|||||||
50
AltStore/Model/InstalledApp.swift
Normal file
50
AltStore/Model/InstalledApp.swift
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// InstalledApp.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/20/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import CoreData
|
||||||
|
|
||||||
|
@objc(InstalledApp)
|
||||||
|
class InstalledApp: NSManagedObject
|
||||||
|
{
|
||||||
|
/* Properties */
|
||||||
|
@NSManaged var bundleIdentifier: String
|
||||||
|
|
||||||
|
@NSManaged var signedDate: Date
|
||||||
|
@NSManaged var expirationDate: Date
|
||||||
|
|
||||||
|
@NSManaged var isBeta: Bool
|
||||||
|
|
||||||
|
/* Relationships */
|
||||||
|
@NSManaged private(set) var app: App?
|
||||||
|
|
||||||
|
private override init(entity: NSEntityDescription, insertInto context: NSManagedObjectContext?)
|
||||||
|
{
|
||||||
|
super.init(entity: entity, insertInto: context)
|
||||||
|
}
|
||||||
|
|
||||||
|
init(app: App, bundleIdentifier: String, signedDate: Date, expirationDate: Date, context: NSManagedObjectContext)
|
||||||
|
{
|
||||||
|
super.init(entity: InstalledApp.entity(), insertInto: context)
|
||||||
|
|
||||||
|
let app = context.object(with: app.objectID) as! App
|
||||||
|
self.app = app
|
||||||
|
|
||||||
|
self.bundleIdentifier = bundleIdentifier
|
||||||
|
self.signedDate = signedDate
|
||||||
|
self.expirationDate = expirationDate
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension InstalledApp
|
||||||
|
{
|
||||||
|
@nonobjc class func fetchRequest() -> NSFetchRequest<InstalledApp>
|
||||||
|
{
|
||||||
|
return NSFetchRequest<InstalledApp>(entityName: "InstalledApp")
|
||||||
|
}
|
||||||
|
}
|
||||||
58
AltStore/My Apps/MyAppsViewController.swift
Normal file
58
AltStore/My Apps/MyAppsViewController.swift
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
//
|
||||||
|
// MyAppsViewController.swift
|
||||||
|
// AltStore
|
||||||
|
//
|
||||||
|
// Created by Riley Testut on 5/9/19.
|
||||||
|
// Copyright © 2019 Riley Testut. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UIKit
|
||||||
|
import Roxas
|
||||||
|
|
||||||
|
class MyAppsViewController: UITableViewController
|
||||||
|
{
|
||||||
|
private lazy var dataSource = self.makeDataSource()
|
||||||
|
|
||||||
|
private lazy var dateFormatter: DateFormatter = {
|
||||||
|
let dateFormatter = DateFormatter()
|
||||||
|
dateFormatter.dateStyle = .short
|
||||||
|
dateFormatter.timeStyle = .none
|
||||||
|
return dateFormatter
|
||||||
|
}()
|
||||||
|
|
||||||
|
override func viewDidLoad()
|
||||||
|
{
|
||||||
|
super.viewDidLoad()
|
||||||
|
|
||||||
|
self.tableView.dataSource = self.dataSource
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private extension MyAppsViewController
|
||||||
|
{
|
||||||
|
func makeDataSource() -> RSTFetchedResultsTableViewDataSource<InstalledApp>
|
||||||
|
{
|
||||||
|
let fetchRequest = InstalledApp.fetchRequest() as NSFetchRequest<InstalledApp>
|
||||||
|
fetchRequest.relationshipKeyPathsForPrefetching = [#keyPath(InstalledApp.app)]
|
||||||
|
fetchRequest.sortDescriptors = [NSSortDescriptor(keyPath: \InstalledApp.app?.name, ascending: true)]
|
||||||
|
fetchRequest.returnsObjectsAsFaults = false
|
||||||
|
|
||||||
|
let dataSource = RSTFetchedResultsTableViewDataSource(fetchRequest: fetchRequest, managedObjectContext: DatabaseManager.shared.viewContext)
|
||||||
|
dataSource.cellConfigurationHandler = { (cell, installedApp, indexPath) in
|
||||||
|
guard let app = installedApp.app else { return }
|
||||||
|
|
||||||
|
cell.textLabel?.text = app.name
|
||||||
|
|
||||||
|
let detailText =
|
||||||
|
"""
|
||||||
|
Signed: \(self.dateFormatter.string(from: installedApp.signedDate))
|
||||||
|
Expires: \(self.dateFormatter.string(from: installedApp.expirationDate))
|
||||||
|
"""
|
||||||
|
|
||||||
|
cell.detailTextLabel?.numberOfLines = 2
|
||||||
|
cell.detailTextLabel?.text = detailText
|
||||||
|
}
|
||||||
|
|
||||||
|
return dataSource
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user