Skip to content

Commit 0fca564

Browse files
committed
Move TechStacks App to ServiceStack Apps
1 parent b52536b commit 0fca564

File tree

102 files changed

+7944
-0
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

102 files changed

+7944
-0
lines changed

src/TechStacks.xcodeproj/project.pbxproj

Lines changed: 353 additions & 0 deletions
Large diffs are not rendered by default.

src/TechStacks.xcodeproj/project.xcworkspace/contents.xcworkspacedata

Lines changed: 7 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/TechStacks/AppData.swift

Lines changed: 193 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,193 @@
1+
//
2+
// AppData.swift
3+
// TechStacks
4+
//
5+
// Created by Demis Bellot on 2/3/15.
6+
// Copyright (c) 2015 ServiceStack LLC. All rights reserved.
7+
//
8+
9+
import UIKit
10+
import Foundation
11+
12+
13+
public class AppData : NSObject
14+
{
15+
var client = JsonServiceClient(baseUrl: "http://techstacks.io")
16+
17+
struct Property {
18+
static let TopTechnologies = "topTechnologies"
19+
static let AllTiers = "allTiers"
20+
static let AllTechnologies = "allTechnologies"
21+
static let AllTechnologyStacks = "allTechnologyStacks"
22+
}
23+
24+
public dynamic var allTiers:[Option] = []
25+
26+
public dynamic var overview:AppOverviewResponse = AppOverviewResponse()
27+
public dynamic var topTechnologies:[TechnologyInfo] = []
28+
29+
public dynamic var allTechnologies:[Technology] = []
30+
public dynamic var allTechnologyStacks:[TechnologyStack] = []
31+
32+
public dynamic var search:String?
33+
public dynamic var filteredTechStacks:[TechnologyStack] = []
34+
public dynamic var filteredTechnologies:[Technology] = []
35+
36+
public var technologyStackCache:[String:GetTechnologyStackResponse] = [:]
37+
public var technologyCache:[String:GetTechnologyResponse] = [:]
38+
39+
override init(){
40+
super.init()
41+
self.loadDefaultImageCaches()
42+
}
43+
44+
func loadOverview() -> Promise<AppOverviewResponse> {
45+
return client.getAsync(AppOverview())
46+
.then(body:{(r:AppOverviewResponse) -> AppOverviewResponse in
47+
self.overview = r
48+
self.allTiers = r.allTiers
49+
self.topTechnologies = r.topTechnologies
50+
return r
51+
})
52+
}
53+
54+
func loadAllTechnologies() -> Promise<GetAllTechnologiesResponse> {
55+
return client.getAsync(GetAllTechnologies())
56+
.then(body:{(r:GetAllTechnologiesResponse) -> GetAllTechnologiesResponse in
57+
self.allTechnologies = r.results
58+
return r
59+
})
60+
}
61+
62+
func loadAllTechStacks() -> Promise<GetAllTechnologyStacksResponse> {
63+
return client.getAsync(GetAllTechnologyStacks())
64+
.then(body:{(r:GetAllTechnologyStacksResponse) -> GetAllTechnologyStacksResponse in
65+
self.allTechnologyStacks = r.results
66+
return r
67+
})
68+
}
69+
70+
func loadTechnologyStack(slug:String) -> Promise<GetTechnologyStackResponse> {
71+
if let response = technologyStackCache[slug] {
72+
return Promise<GetTechnologyStackResponse> { (complete,reject) in complete(response) }
73+
}
74+
75+
var request = GetTechnologyStack()
76+
request.slug = slug
77+
return client.getAsync(request)
78+
.then(body:{ (r:GetTechnologyStackResponse) -> GetTechnologyStackResponse in
79+
self.technologyStackCache[r.result!.slug!] = r
80+
return r
81+
})
82+
}
83+
84+
func searchTechStacks(query:String) -> Promise<QueryResponse<TechnologyStack>> {
85+
self.search = query
86+
87+
let request = FindTechStacks<TechnologyStack>()
88+
return client.getAsync(request, query:["NameContains":query, "DescriptionContains":query])
89+
.then(body:{(r:QueryResponse<TechnologyStack>) -> QueryResponse<TechnologyStack> in
90+
self.filteredTechStacks = r.results
91+
return r
92+
})
93+
}
94+
95+
func loadTechnology(slug:String) -> Promise<GetTechnologyResponse> {
96+
if let response = technologyCache[slug] {
97+
return Promise<GetTechnologyResponse> { (complete,reject) in complete(response) }
98+
}
99+
100+
var request = GetTechnology()
101+
request.slug = slug
102+
return client.getAsync(request)
103+
.then(body:{ (r:GetTechnologyResponse) -> GetTechnologyResponse in
104+
self.technologyCache[r.technology!.slug!] = r
105+
return r
106+
})
107+
}
108+
109+
func searchTechnologies(query:String) -> Promise<QueryResponse<Technology>> {
110+
self.search = query
111+
112+
let request = FindTechnologies<Technology>()
113+
return client.getAsync(request, query:["NameContains":query, "DescriptionContains":query])
114+
.then(body:{(r:QueryResponse<Technology>) -> QueryResponse<Technology> in
115+
self.filteredTechnologies = r.results
116+
return r
117+
})
118+
}
119+
120+
var imageCache:[String:UIImage] = [:]
121+
func loadDefaultImageCaches() {
122+
imageCache["stacks"] = UIImage(named: "stacks")
123+
124+
UIGraphicsBeginImageContextWithOptions(CGSizeMake(858, 689), false, 0.0)
125+
imageCache["blankScreenshot"] = UIGraphicsGetImageFromCurrentImageContext()
126+
UIGraphicsEndImageContext()
127+
}
128+
129+
public func loadAllImagesAsync(urls:[String]) -> Promise<[String:UIImage?]> {
130+
var images = [String:UIImage?]()
131+
return Promise<[String:UIImage?]> { (complete, reject) in
132+
for url in urls {
133+
self.loadImageAsync(url)
134+
.then(body: { (img:UIImage?) -> Void in
135+
images[url] = img
136+
if images.count == urls.count {
137+
return complete(images)
138+
}
139+
})
140+
}
141+
}
142+
}
143+
144+
public func loadImageAsync(url:String) -> Promise<UIImage?> {
145+
if let image = imageCache[url] {
146+
return Promise<UIImage?> { (complete, reject) in complete(image) }
147+
}
148+
149+
return client.getDataAsync(url)
150+
.then(body: { (data:NSData) -> UIImage? in
151+
if let image = UIImage(data:data) {
152+
self.imageCache[url] = image
153+
return image
154+
}
155+
return nil
156+
})
157+
}
158+
159+
/* KVO Observable helpers */
160+
var observedProperties = [NSObject:[String]]()
161+
var ctx:AnyObject = 1
162+
163+
public func observe(observer: NSObject, properties:[String]) {
164+
for property in properties {
165+
self.observe(observer, property: property)
166+
}
167+
}
168+
169+
public func observe(observer: NSObject, property:String) {
170+
self.addObserver(observer, forKeyPath: property, options: .New | .Old, context: &ctx)
171+
172+
var properties = observedProperties[observer] ?? [String]()
173+
properties.append(property)
174+
observedProperties[observer] = properties
175+
}
176+
177+
public func unobserve(observer: NSObject) {
178+
if let properties = observedProperties[observer] {
179+
for property in properties {
180+
self.removeObserver(observer, forKeyPath: property, context: &ctx)
181+
}
182+
}
183+
}
184+
185+
//Clear caches if we receive memory warning
186+
func resetCache() {
187+
imageCache = [:]
188+
technologyStackCache = [:]
189+
technologyCache = [:]
190+
loadDefaultImageCaches()
191+
}
192+
193+
}

src/TechStacks/AppDelegate.swift

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
//
2+
// AppDelegate.swift
3+
// TechStacks
4+
//
5+
// Created by Demis Bellot on 2/2/15.
6+
// Copyright (c) 2015 ServiceStack LLC. All rights reserved.
7+
//
8+
9+
import UIKit
10+
11+
@UIApplicationMain
12+
class AppDelegate: UIResponder, UIApplicationDelegate {
13+
14+
var window: UIWindow?
15+
16+
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
17+
// Override point for customization after application launch.
18+
19+
//https://coderwall.com/p/dyqrfa/customize-navigation-bar-appearance-with-swift
20+
var navigationBarAppearace = UINavigationBar.appearance()
21+
navigationBarAppearace.translucent = false
22+
navigationBarAppearace.tintColor = UIColor.whiteColor()
23+
navigationBarAppearace.barTintColor = UIColor(red: 0.0, green: 0.58431372550000005, blue: 0.96078431369999995, alpha: 1.0)
24+
navigationBarAppearace.titleTextAttributes = [NSForegroundColorAttributeName:UIColor.whiteColor()]
25+
UIApplication.sharedApplication().statusBarStyle = UIStatusBarStyle.LightContent
26+
27+
return true
28+
}
29+
30+
func applicationWillResignActive(application: UIApplication) {
31+
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
32+
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
33+
}
34+
35+
func applicationDidEnterBackground(application: UIApplication) {
36+
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
37+
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
38+
}
39+
40+
func applicationWillEnterForeground(application: UIApplication) {
41+
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
42+
}
43+
44+
func applicationDidBecomeActive(application: UIApplication) {
45+
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
46+
}
47+
48+
func applicationWillTerminate(application: UIApplication) {
49+
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
50+
}
51+
52+
func applicationDidReceiveMemoryWarning(application: UIApplication) {
53+
appData.resetCache()
54+
}
55+
56+
var appData = AppData()
57+
}
58+
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="14D72i" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
3+
<dependencies>
4+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
5+
</dependencies>
6+
<objects>
7+
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
8+
<placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
9+
<view contentMode="bottomRight" id="iN0-l3-epB">
10+
<rect key="frame" x="0.0" y="0.0" width="352" height="584"/>
11+
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
12+
<subviews>
13+
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" image="launch-view" translatesAutoresizingMaskIntoConstraints="NO" id="0MF-uz-kaj">
14+
<rect key="frame" x="20" y="20" width="312" height="564"/>
15+
</imageView>
16+
</subviews>
17+
<color key="backgroundColor" red="0.0" green="0.58431372550000005" blue="0.96078431369999995" alpha="1" colorSpace="calibratedRGB"/>
18+
<color key="tintColor" white="1" alpha="1" colorSpace="calibratedWhite"/>
19+
<constraints>
20+
<constraint firstAttribute="bottom" secondItem="0MF-uz-kaj" secondAttribute="bottom" id="Dkj-3h-w49"/>
21+
<constraint firstItem="0MF-uz-kaj" firstAttribute="centerX" secondItem="iN0-l3-epB" secondAttribute="centerX" id="r2b-iz-uhG"/>
22+
</constraints>
23+
<nil key="simulatedStatusBarMetrics"/>
24+
<freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
25+
<point key="canvasLocation" x="639" y="309"/>
26+
</view>
27+
</objects>
28+
<resources>
29+
<image name="launch-view" width="312" height="564"/>
30+
</resources>
31+
</document>

0 commit comments

Comments
 (0)