Commit 7d78da5b authored by domenicw's avatar domenicw
Browse files

Merge zdenis and master

parent 7f4f7a08
//
// Local+Extension.swift
// Amiv
//
// Created by Domenic Wüthrich on 12.10.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public extension Locale {
public enum AppLanguage: String {
case german = "de"
case english = "en"
}
public static func current() -> AppLanguage {
if let language = Locale.preferredLanguages.first, language == AppLanguage.german.rawValue {
return .german
} else {
return .english
}
}
public static func getLocalizedString(english: String, german: String) -> String {
switch Locale.current() {
case .english:
return english
case .german:
return german
}
}
}
<?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">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
//
// KeychainKey.swift
// Amiv
//
// Created by Domenic Wüthrich on 23.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public enum KeychainKey: String {
case username
case password
case authToken
case userID
}
extension KeychainKey {
/// Gets associated value of key from keychain store
public func getString() -> String? {
let keychain = KeychainSwift()
let string = keychain.get(self.rawValue)
return string
}
}
//
// EventViewModel.swift
// Amiv
//
// Created by Domenic Wüthrich on 18.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public struct EventViewModel {
// MARK: - Variables
let viewTitle: String
let events: [AMIVEvent]
// MARK: - Initializers
public init(viewTitle: String, events: [AMIVEvent]) {
self.viewTitle = viewTitle
self.events = events
}
public init(response: EventsResponse) {
self.init(viewTitle: "Events", events: response.events)
}
}
extension EventViewModel {
public static func empty() -> EventViewModel {
return self.init(viewTitle: "Events", events: [])
}
}
//
// JobsViewModel.swift
// Amiv
//
// Created by Domenic Wüthrich on 12.10.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public struct JobsViewModel {
// MARK: - Variables
var viewTitle: String
var jobOffers: [JobOffer]
// MARK: - Initializers
public init(viewTitle: String, jobOffers: [JobOffer]) {
self.viewTitle = viewTitle
self.jobOffers = jobOffers
}
public init(jobOffers: [JobOffer]) {
self.init(viewTitle: "Jobs", jobOffers: jobOffers)
}
}
extension JobsViewModel {
public static func empty() -> JobsViewModel {
return .init(jobOffers: [])
}
}
//
// AppNavigator.swift
// Amiv
//
// Created by Domenic Wüthrich on 18.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
import UIKit
public class AppNavigator: Navigator {
// MARK: - Variables
private var childNavigators: [Navigator] = []
public var rootViewController: UIViewController {
return tabBarController
}
private var tabBarController: UITabBarController
// MARK: - Tabs
private enum Tab: Int {
//case home
case events
case jobs
case apps
case settings
}
// MARK: - Initializers
public init() {
self.tabBarController = UITabBarController()
self.createTabs()
}
// MARK: - Tab Bar Tabs
private func createTabs() {
// Create all tabs
//self.createHomeTab()
self.createEventsTab()
self.createJobsTab()
self.createAmivApplicationTab()
self.createSettingsTab()
// Make tabBarController ready
self.tabBarController.viewControllers = self.childNavigators.map({ $0.rootViewController })
self.tabBarController.selectedIndex = Tab.events.rawValue
self.tabBarController.tabBar.tintColor = .amivRed
}
private func createHomeTab() {
let home = HomeNavigator()
self.childNavigators.append(home)
}
private func createEventsTab() {
let events = EventsNavigator()
self.childNavigators.append(events)
}
private func createJobsTab() {
let jobs = JobsNavigator()
self.childNavigators.append(jobs)
}
private func createAmivApplicationTab() {
let app = AmivMicroAppsNavigator()
app.rootViewController.tabBarItem = UITabBarItem(title: "Apps", image: UIImage(named: "appsTab"), tag: Tab.settings.rawValue)
self.childNavigators.append(app)
}
private func createSettingsTab() {
let settings = SettingsNavigator()
settings.rootViewController.tabBarItem = UITabBarItem(title: "Settings", image: UIImage(named: "settings"), tag: Tab.settings.rawValue)
self.childNavigators.append(settings)
}
}
//
// EventsNavigator.swift
// Amiv
//
// Created by Domenic Wüthrich on 20.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
import UIKit
public class EventsNavigator: Navigator {
// MARK: - Variables
public let networkManager = NetworkManager<AMIVApiEvents>()
public var rootViewController: UIViewController {
return self.navigationController
}
private var navigationController: UINavigationController
// MARK: - Initializers
public init() {
let events = EventsViewController(model: .empty())
self.navigationController = UINavigationController(rootViewController: events)
self.navigationController.navigationBar.tintColor = .amivRed
events.delegate = self
self.refreshData(events)
self.networkManager.getEventSignups { (events, error) in
guard let event = events?.first else {
return
}
self.networkManager.signupTo(event, { (success, error) in
debugPrint(success)
debugPrint(error)
})
}
}
// MARK: - Navigation
private func goToEventDetailView(model: GenericInfoViewControllerModel) {
let info = GenericInfoViewController(model: model)
info.delegate = self
self.navigationController.pushViewController(info, animated: true)
}
}
extension EventsNavigator: EventsViewControllerDelegate {
public func didSelectEvent(_ viewController: EventsViewController, event: AMIVEvent) {
if let eventImage = event.image {
self.networkManager.getImage(for: eventImage.filePath) { (data, error) in
let model: GenericInfoViewControllerModel
if error == nil, let data = data {
let image = UIImage(data: data)
model = GenericInfoViewControllerModel(event: event, image: image)
} else {
model = GenericInfoViewControllerModel(event: event, image: nil)
}
DispatchQueue.main.async {
self.goToEventDetailView(model: model)
}
}
} else {
let model = GenericInfoViewControllerModel(event: event, image: nil)
self.goToEventDetailView(model: model)
}
}
public func refreshData(_ viewController: EventsViewController) {
self.networkManager.getEvents { (response, error) in
guard let response = response else {
DispatchQueue.main.async {
viewController.tableView.refreshControl?.endRefreshing()
}
return
}
DispatchQueue.main.async {
viewController.model = EventViewModel(response: response)
}
}
}
}
extension EventsNavigator: GenericInfoViewControllerDelegate {
public func buttonTapped(_ viewController: GenericInfoViewController, action: GenericInfoViewControllerAction) {
debugPrint("Info View button tapped")
// TODO: - Sign up for event
}
}
//
// OnboardingNavigator.swift
// Amiv
//
// Created by Domenic Wüthrich on 18.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
import UIKit
public class OnboardingNavigator: Navigator {
// MARK: - Variables
let networkManager = NetworkManager<AMIVApiSession>()
public var delegate: OnboardingNavigatorDelegate?
public var rootViewController: UIViewController {
return self.navigationController
}
private var navigationController: UINavigationController
// MARK: - Initializers
public init() {
let info = InfoViewController(model: .create())
self.navigationController = UINavigationController(rootViewController: info)
info.delegate = self
}
// MARK: - Navigation
private func presentLogin() {
let login = LoginViewController(model: .createOnboarding())
login.delegate = self
self.navigationController.present(login, animated: true, completion: nil)
}
}
extension OnboardingNavigator: InfoViewControllerDelegate {
public func buttonPressed() {
self.presentLogin()
}
public func smallButtonPressed() {
self.delegate?.onboardingFinished()
}
}
extension OnboardingNavigator: LoginViewControllerDelegate {
public func login(_ viewController: LoginViewController, username: String, password: String) {
// TODO: - Check for valid credentials
debugPrint("Logging in with username: \(username) and password: \(password)")
self.networkManager.authenticate(username: username, password: password) { (response, error) in
guard let response = response else {
DispatchQueue.main.async {
viewController.loginFailed(with: "Incorrect Username or Password.\nPlease try again.")
}
return
}
// Save token into secure and encrypted keychain
SessionManager.save(response)
let userManager = NetworkManager<AMIVApiUser>()
userManager.getUserInfo({ (user, error) in
guard error == nil, let user = user else {
return
}
let _ = user.saveLocal()
})
DispatchQueue.main.async {
self.delegate?.onboardingFinished()
}
}
}
public func smallButtonTapped(_ viewController: LoginViewController) {
self.delegate?.onboardingFinished()
}
}
//
// AmivRootNavigator.swift
// Amiv
//
// Created by Domenic Wüthrich on 18.09.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
import UIKit
public class AmivRootNavigator: RootNavigator {
// MARK: - Variables
public var window: UIWindow
public var currentNavigator: Navigator?
// MARK: - Initializers
public init(window: UIWindow) {
self.window = window
if SessionManager.isLoggedIn {
self.goToApp()
} else {
self.goToOnboarding()
}
}
// MARK: - Navigation
private func goToApp() {
let app = AppNavigator()
self.window.rootViewController = app.rootViewController
self.currentNavigator = app
}
private func goToOnboarding() {
let onboarding = OnboardingNavigator()
onboarding.delegate = self
self.window.rootViewController = onboarding.rootViewController
self.currentNavigator = onboarding
}
}
extension AmivRootNavigator: OnboardingNavigatorDelegate {
public func onboardingFinished() {
self.goToApp()
}
}
//
// AMIVApiJobs.swift
// Amiv
//
// Created by Domenic Wüthrich on 10.10.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public enum AMIVApiJobs: EndPointType {
case jobs
case media(_ path: String)
}
extension AMIVApiJobs {
public var path: String {
switch self {
case .jobs:
return "/joboffers"
case .media(let path):
return path
}
}
public var httpMethod: HTTPMethod {
switch self {
case .jobs, .media:
return .get
}
}
public var task: HTTPTask {
switch self {
case .jobs, .media:
return .request
}
}
public var headers: HTTPHeaders? {
switch self {
case .jobs, .media:
return nil
}
}
public var isAuthenticationRequired: Bool {
return true
}
}
//
// AMIVApiUser.swift
// Amiv
//
// Created by Domenic Wüthrich on 13.10.18.
// Copyright © 2018 Amiv an der ETH. All rights reserved.
//
import Foundation
public enum AMIVApiUser {
case userInfo
case allUsers
}
extension AMIVApiUser: EndPointType {
public var path: String {
switch self {
case .userInfo:
if let id = SessionManager.userID {
return "/users/\(id)"