Adds basic AppsViewController implementation

This commit is contained in:
Riley Testut
2019-05-09 15:29:54 -07:00
parent e5957e61a2
commit f4a3a09cba
20 changed files with 453 additions and 68 deletions

View File

@@ -8,13 +8,18 @@
/* Begin PBXBuildFile section */
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476D2284B9A500981D42 /* AppDelegate.swift */; };
BFD247702284B9A500981D42 /* FirstViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476F2284B9A500981D42 /* FirstViewController.swift */; };
BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2476F2284B9A500981D42 /* AppsViewController.swift */; };
BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247712284B9A500981D42 /* SecondViewController.swift */; };
BFD247752284B9A500981D42 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247732284B9A500981D42 /* Main.storyboard */; };
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = BFD247762284B9A700981D42 /* Assets.xcassets */; };
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = BFD247782284B9A700981D42 /* LaunchScreen.storyboard */; };
BFD247872284BB4200981D42 /* Roxas.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = BFD247862284BB3B00981D42 /* Roxas.framework */; };
BFD247882284BB4200981D42 /* Roxas.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = BFD247862284BB3B00981D42 /* Roxas.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478B2284C4C300981D42 /* AppIconImageView.swift */; };
BFD2478F2284C8F900981D42 /* Button.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD2478E2284C8F900981D42 /* Button.swift */; };
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247922284D4B700981D42 /* AppTableViewCell.swift */; };
BFD247952284D7BD00981D42 /* Apps.plist in Resources */ = {isa = PBXBuildFile; fileRef = BFD247942284D7BD00981D42 /* Apps.plist */; };
BFD2479A2284D80900981D42 /* App.swift in Sources */ = {isa = PBXBuildFile; fileRef = BFD247992284D80900981D42 /* App.swift */; };
/* End PBXBuildFile section */
/* Begin PBXCopyFilesBuildPhase section */
@@ -34,13 +39,18 @@
/* Begin PBXFileReference section */
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>"; };
BFD2476F2284B9A500981D42 /* FirstViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FirstViewController.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>"; };
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>"; };
BFD247792284B9A700981D42 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
BFD2477B2284B9A700981D42 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
BFD247862284BB3B00981D42 /* Roxas.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = Roxas.framework; sourceTree = BUILT_PRODUCTS_DIR; };
BFD2478B2284C4C300981D42 /* AppIconImageView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconImageView.swift; sourceTree = "<group>"; };
BFD2478E2284C8F900981D42 /* Button.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Button.swift; sourceTree = "<group>"; };
BFD247922284D4B700981D42 /* AppTableViewCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppTableViewCell.swift; sourceTree = "<group>"; };
BFD247942284D7BD00981D42 /* Apps.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Apps.plist; sourceTree = "<group>"; };
BFD247992284D80900981D42 /* App.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = App.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
@@ -76,12 +86,13 @@
isa = PBXGroup;
children = (
BFD2476D2284B9A500981D42 /* AppDelegate.swift */,
BFD2476F2284B9A500981D42 /* FirstViewController.swift */,
BFD247712284B9A500981D42 /* SecondViewController.swift */,
BFD247732284B9A500981D42 /* Main.storyboard */,
BFD247762284B9A700981D42 /* Assets.xcassets */,
BFD247782284B9A700981D42 /* LaunchScreen.storyboard */,
BFD2477B2284B9A700981D42 /* Info.plist */,
BFD2478A2284C49000981D42 /* Apps */,
BFD247982284D7FC00981D42 /* Model */,
BFD2478D2284C4C700981D42 /* Components */,
BFD247712284B9A500981D42 /* SecondViewController.swift */,
BFD247962284D7C100981D42 /* Resources */,
BFD247972284D7D800981D42 /* Supporting Files */,
);
path = AltStore;
sourceTree = "<group>";
@@ -94,6 +105,50 @@
name = Frameworks;
sourceTree = "<group>";
};
BFD2478A2284C49000981D42 /* Apps */ = {
isa = PBXGroup;
children = (
BFD2476F2284B9A500981D42 /* AppsViewController.swift */,
BFD247922284D4B700981D42 /* AppTableViewCell.swift */,
);
path = Apps;
sourceTree = "<group>";
};
BFD2478D2284C4C700981D42 /* Components */ = {
isa = PBXGroup;
children = (
BFD2478B2284C4C300981D42 /* AppIconImageView.swift */,
BFD2478E2284C8F900981D42 /* Button.swift */,
);
path = Components;
sourceTree = "<group>";
};
BFD247962284D7C100981D42 /* Resources */ = {
isa = PBXGroup;
children = (
BFD247762284B9A700981D42 /* Assets.xcassets */,
BFD247942284D7BD00981D42 /* Apps.plist */,
);
path = Resources;
sourceTree = "<group>";
};
BFD247972284D7D800981D42 /* Supporting Files */ = {
isa = PBXGroup;
children = (
BFD247782284B9A700981D42 /* LaunchScreen.storyboard */,
BFD2477B2284B9A700981D42 /* Info.plist */,
);
name = "Supporting Files";
sourceTree = "<group>";
};
BFD247982284D7FC00981D42 /* Model */ = {
isa = PBXGroup;
children = (
BFD247992284D80900981D42 /* App.swift */,
);
path = Model;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXNativeTarget section */
@@ -153,6 +208,7 @@
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BFD247952284D7BD00981D42 /* Apps.plist in Resources */,
BFD2477A2284B9A700981D42 /* LaunchScreen.storyboard in Resources */,
BFD247772284B9A700981D42 /* Assets.xcassets in Resources */,
BFD247752284B9A500981D42 /* Main.storyboard in Resources */,
@@ -166,9 +222,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
BFD2478F2284C8F900981D42 /* Button.swift in Sources */,
BFD247722284B9A500981D42 /* SecondViewController.swift in Sources */,
BFD2478C2284C4C300981D42 /* AppIconImageView.swift in Sources */,
BFD2476E2284B9A500981D42 /* AppDelegate.swift in Sources */,
BFD247702284B9A500981D42 /* FirstViewController.swift in Sources */,
BFD247702284B9A500981D42 /* AppsViewController.swift in Sources */,
BFD2479A2284D80900981D42 /* App.swift in Sources */,
BFD247932284D4B700981D42 /* AppTableViewCell.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};

View File

@@ -0,0 +1,53 @@
//
// AppTableViewCell.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
@objc class AppTableViewCell: UITableViewCell
{
@IBOutlet var nameLabel: UILabel!
@IBOutlet var subtitleLabel: UILabel!
@IBOutlet var appIconImageView: UIImageView!
@IBOutlet var button: UIButton!
override func awakeFromNib()
{
super.awakeFromNib()
self.selectionStyle = .none
}
override func setHighlighted(_ highlighted: Bool, animated: Bool)
{
super.setHighlighted(highlighted, animated: animated)
self.update()
}
override func setSelected(_ selected: Bool, animated: Bool)
{
super.setSelected(selected, animated: animated)
self.update()
}
}
private extension AppTableViewCell
{
func update()
{
if self.isHighlighted || self.isSelected
{
self.contentView.backgroundColor = UIColor(white: 0.9, alpha: 1.0)
}
else
{
self.contentView.backgroundColor = .white
}
}
}

View File

@@ -0,0 +1,52 @@
//
// AppsViewController.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
import Roxas
class AppsViewController: UITableViewController
{
private lazy var dataSource = self.makeDataSource()
override func viewDidLoad()
{
super.viewDidLoad()
self.tableView.dataSource = self.dataSource
// Hide trailing row separators.
self.tableView.tableFooterView = UIView()
}
}
private extension AppsViewController
{
func makeDataSource() -> RSTArrayTableViewDataSource<App>
{
let appsFileURL = Bundle.main.url(forResource: "Apps", withExtension: "plist")!
do
{
let data = try Data(contentsOf: appsFileURL)
let apps = try PropertyListDecoder().decode([App].self, from: data)
let dataSource = RSTArrayTableViewDataSource(items: apps)
dataSource.cellConfigurationHandler = { (cell, app, indexPath) in
let cell = cell as! AppTableViewCell
cell.nameLabel.text = app.name
cell.subtitleLabel.text = app.subtitle
cell.appIconImageView.image = UIImage(named: app.iconName)
}
return dataSource
}
catch
{
fatalError("Failed to load apps. \(error)")
}
}
}

View File

@@ -1,61 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="13122.16" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="49e-Tb-3d3">
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="14490.70" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="49e-Tb-3d3">
<device id="retina4_7" orientation="portrait">
<adaptation id="fullscreen"/>
</device>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="13104.12"/>
<deployment identifier="iOS"/>
<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"/>
</dependencies>
<scenes>
<!--First-->
<scene sceneID="hNz-n2-bh7">
<objects>
<viewController id="9pv-A4-QxB" customClass="FirstViewController" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="tsR-hK-woN">
<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="First View" textAlignment="center" lineBreakMode="tailTruncation" minimumFontSize="10" translatesAutoresizingMaskIntoConstraints="NO" id="KQZ-1w-vlD">
<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 FirstViewController" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="A5M-7J-77L">
<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 firstAttribute="centerX" secondItem="KQZ-1w-vlD" secondAttribute="centerX" id="6BV-lF-sBN"/>
<constraint firstItem="A5M-7J-77L" firstAttribute="top" secondItem="KQZ-1w-vlD" secondAttribute="bottom" constant="8" symbolic="YES" id="cfb-er-3JN"/>
<constraint firstItem="A5M-7J-77L" firstAttribute="centerX" secondItem="KQZ-1w-vlD" secondAttribute="centerX" id="e1l-AV-tCB"/>
<constraint firstAttribute="centerY" secondItem="KQZ-1w-vlD" secondAttribute="centerY" id="exm-UA-ej4"/>
</constraints>
<viewLayoutGuide key="safeArea" id="PQr-Ze-W5v"/>
</view>
<tabBarItem key="tabBarItem" title="First" image="first" id="acW-dT-cKf"/>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="W5J-7L-Pyd" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="750" y="-320"/>
</scene>
<!--Second-->
<scene sceneID="wg7-f3-ORb">
<objects>
<viewController id="8rJ-Kc-sve" customClass="SecondViewController" customModuleProvider="target" sceneMemberID="viewController">
<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"/>
@@ -86,14 +57,125 @@
<color key="backgroundColor" red="0.0" green="0.0" blue="0.0" alpha="0.0" colorSpace="custom" customColorSpace="sRGB"/>
</tabBar>
<connections>
<segue destination="9pv-A4-QxB" kind="relationship" relationship="viewControllers" id="u7Y-xg-7CH"/>
<segue destination="8rJ-Kc-sve" kind="relationship" relationship="viewControllers" id="lzU-1b-eKA"/>
<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"/>
</connections>
</tabBarController>
<placeholder placeholderIdentifier="IBFirstResponder" id="HuB-VB-40B" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="0.0" y="0.0"/>
</scene>
<!--Apps-->
<scene sceneID="JlP-x7-lBT">
<objects>
<tableViewController id="q89-7o-3rs" customClass="AppsViewController" 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="10Y-Ge-TH3">
<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" rowHeight="118" id="dJn-Mf-F1h" customClass="AppTableViewCell" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="28" width="375" height="118"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="dJn-Mf-F1h" id="gzF-hx-pLZ">
<rect key="frame" x="0.0" y="0.0" width="375" height="117.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" alignment="top" spacing="15" translatesAutoresizingMaskIntoConstraints="NO" id="tdM-M1-iDO">
<rect key="frame" x="0.0" y="0.0" width="375" height="117.5"/>
<subviews>
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="gsm-sN-j56" customClass="AppIconImageView" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="15" y="15" width="88" height="88"/>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
<constraints>
<constraint firstAttribute="width" constant="88" id="azK-Tb-i28"/>
<constraint firstAttribute="height" constant="88" id="kNm-96-9zq"/>
</constraints>
</imageView>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="equalSpacing" alignment="top" translatesAutoresizingMaskIntoConstraints="NO" id="703-qg-th2">
<rect key="frame" x="118" y="15" width="242" height="87.5"/>
<subviews>
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="2" translatesAutoresizingMaskIntoConstraints="NO" id="opz-OR-arv">
<rect key="frame" x="0.0" y="0.0" width="199.5" height="43"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="Delta" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="d4v-IK-LuC">
<rect key="frame" x="0.0" y="0.0" width="199.5" height="23"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" verticalCompressionResistancePriority="1000" text="All-in-one Nintendo emulator" textAlignment="natural" lineBreakMode="tailTruncation" numberOfLines="2" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xnf-XX-iX9">
<rect key="frame" x="0.0" y="25" width="199.5" height="18"/>
<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>
<button opaque="NO" contentMode="scaleToFill" verticalHuggingPriority="1000" verticalCompressionResistancePriority="1000" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ScM-Z2-rAe" customClass="Button" customModule="AltStore" customModuleProvider="target">
<rect key="frame" x="0.0" y="57.5" width="72" height="30"/>
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="15"/>
<color key="tintColor" red="0.0" green="0.47843137250000001" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
<state key="normal" title="Download"/>
</button>
</subviews>
<constraints>
<constraint firstItem="ScM-Z2-rAe" firstAttribute="top" relation="greaterThanOrEqual" secondItem="opz-OR-arv" secondAttribute="bottom" priority="900" constant="14" id="p93-Jj-26G"/>
</constraints>
</stackView>
</subviews>
<constraints>
<constraint firstAttribute="bottom" secondItem="703-qg-th2" secondAttribute="bottom" constant="15" id="omo-uf-DZn"/>
</constraints>
<edgeInsets key="layoutMargins" top="15" left="15" bottom="14.5" right="15"/>
</stackView>
</subviews>
<constraints>
<constraint firstItem="tdM-M1-iDO" firstAttribute="top" secondItem="gzF-hx-pLZ" secondAttribute="top" id="Dph-Xu-UMN"/>
<constraint firstAttribute="trailing" secondItem="tdM-M1-iDO" secondAttribute="trailing" id="ITi-qo-EuU"/>
<constraint firstAttribute="bottom" secondItem="tdM-M1-iDO" secondAttribute="bottom" id="iyZ-M1-q9y"/>
<constraint firstItem="tdM-M1-iDO" firstAttribute="leading" secondItem="gzF-hx-pLZ" secondAttribute="leading" id="sig-Cf-p45"/>
</constraints>
</tableViewCellContentView>
<inset key="separatorInset" minX="118" minY="0.0" maxX="0.0" maxY="0.0"/>
<connections>
<outlet property="appIconImageView" destination="gsm-sN-j56" id="1ip-RW-xBe"/>
<outlet property="button" destination="ScM-Z2-rAe" id="VnW-vG-JCc"/>
<outlet property="nameLabel" destination="d4v-IK-LuC" id="wFw-Js-PXE"/>
<outlet property="subtitleLabel" destination="xnf-XX-iX9" id="CYk-ud-YHz"/>
</connections>
</tableViewCell>
</prototypes>
<connections>
<outlet property="dataSource" destination="q89-7o-3rs" id="HlP-Lu-70n"/>
<outlet property="delegate" destination="q89-7o-3rs" id="D5P-te-Kct"/>
</connections>
</tableView>
<navigationItem key="navigationItem" title="Apps" id="8hf-te-CkC"/>
</tableViewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="ogT-wc-s7p" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="1519" y="-319"/>
</scene>
<!--Apps-->
<scene sceneID="YAm-Ca-4vd">
<objects>
<navigationController automaticallyAdjustsScrollViewInsets="NO" id="XF0-gk-CxQ" sceneMemberID="viewController">
<tabBarItem key="tabBarItem" title="Apps" image="first" id="cDk-uR-lGN"/>
<toolbarItems/>
<navigationBar key="navigationBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" largeTitles="YES" id="w2b-o0-FNx">
<rect key="frame" x="0.0" y="20" width="375" height="96"/>
<autoresizingMask key="autoresizingMask"/>
</navigationBar>
<nil name="viewControllers"/>
<connections>
<segue destination="q89-7o-3rs" kind="relationship" relationship="rootViewController" id="yGz-tn-mRJ"/>
</connections>
</navigationController>
<placeholder placeholderIdentifier="IBFirstResponder" id="4cQ-6T-2Cl" userLabel="First Responder" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="749.60000000000002" y="-318.89055472263868"/>
</scene>
</scenes>
<resources>
<image name="first" width="30" height="30"/>

View File

@@ -0,0 +1,38 @@
//
// AppIconImageView.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
class AppIconImageView: UIImageView
{
override func awakeFromNib()
{
super.awakeFromNib()
self.contentMode = .scaleAspectFill
self.clipsToBounds = true
self.layer.borderWidth = 0.5
self.layer.borderColor = UIColor.lightGray.cgColor
// Allows us to match system look for app icons.
if self.layer.responds(to: Selector(("continuousCorners")))
{
self.layer.setValue(true, forKey: "continuousCorners")
}
}
override func layoutSubviews()
{
super.layoutSubviews()
// Based off of 60pt icon having 12pt radius.
let radius = self.bounds.height / 5
self.layer.cornerRadius = radius
}
}

View File

@@ -0,0 +1,51 @@
//
// Button.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
class Button: UIButton
{
override var intrinsicContentSize: CGSize {
var size = super.intrinsicContentSize
size.width += 20
return size
}
override func awakeFromNib()
{
super.awakeFromNib()
self.setTitleColor(.white, for: .normal)
self.layer.masksToBounds = true
self.layer.cornerRadius = 8
self.update()
}
override func tintColorDidChange()
{
super.tintColorDidChange()
self.update()
}
override var isHighlighted: Bool {
didSet {
self.update()
}
}
}
private extension Button
{
func update()
{
self.backgroundColor = self.tintColor
}
}

View File

@@ -1,20 +0,0 @@
//
// FirstViewController.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import UIKit
class FirstViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}

17
AltStore/Model/App.swift Normal file
View File

@@ -0,0 +1,17 @@
//
// App.swift
// AltStore
//
// Created by Riley Testut on 5/9/19.
// Copyright © 2019 Riley Testut. All rights reserved.
//
import Foundation
class App: NSObject, Codable
{
var name: String
var subtitle: String
var iconName: String
}

View File

@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>name</key>
<string>Delta</string>
<key>subtitle</key>
<string>All-in-one Nintendo emulator</string>
<key>iconName</key>
<string>DeltaIcon</string>
</dict>
<dict>
<key>name</key>
<string>Clipboard Manager</string>
<key>subtitle</key>
<string>Simple but powerful clipboard manager</string>
<key>iconName</key>
<string>ClipboardIcon</string>
</dict>
</array>
</plist>

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.9 KiB

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "ClipboardIcon.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

View File

@@ -0,0 +1,12 @@
{
"images" : [
{
"idiom" : "universal",
"filename" : "DeltaIcon.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

View File

@@ -0,0 +1,6 @@
{
"info" : {
"version" : 1,
"author" : "xcode"
}
}