Skip to content

Commit

Permalink
Initial commit for new application detail screen
Browse files Browse the repository at this point in the history
  • Loading branch information
zenangst committed Apr 10, 2019
1 parent bafa5e7 commit 4db977d
Show file tree
Hide file tree
Showing 25 changed files with 419 additions and 42 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ osx_image: xcode10.2
language: objective-c

script:
- set -o pipefail && xcodebuild -project Syncalicious.xcodeproj -scheme "Tests" -sdk macosx clean test build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED="NO" | xcpretty
- set -o pipefail && xcodebuild -workspace Syncalicious.xcworkspace -scheme "Tests" -sdk macosx clean test build CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED="NO" | xcpretty

after_success:
- bash <(curl -s https://codecov.io/bash)
Expand Down
9 changes: 9 additions & 0 deletions Podfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
source 'https://github.com/CocoaPods/Specs.git'
platform :macos, '10.14'

# Frameworks
pod 'Family'

target 'Syncalicious'
target 'Tests'

16 changes: 16 additions & 0 deletions Podfile.lock
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
PODS:
- Family (0.14.3)

DEPENDENCIES:
- Family

SPEC REPOS:
https://github.com/cocoapods/specs.git:
- Family

SPEC CHECKSUMS:
Family: e895808117f577305a6b5cabd4fc7463ad262e1f

PODFILE CHECKSUM: 577eb548a5a12c3ca5c8d9a8a4ae97a7f630192b

COCOAPODS: 1.6.0
10 changes: 7 additions & 3 deletions Sources/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -109,8 +109,9 @@ class AppDelegate: NSObject, NSApplicationDelegate, BackupControllerDelegate, Ap
"title": item.propertyList.bundleName,
"subtitle": subtitle,
"bundleIdentifier": item.propertyList.bundleIdentifier,
"path": item.path,
"enabled": true
"path": item.url,
"enabled": true,
"model": item
])
}
let models = applications
Expand All @@ -119,7 +120,10 @@ class AppDelegate: NSObject, NSApplicationDelegate, BackupControllerDelegate, Ap

if let mainViewController = mainViewController {
mainViewController.reload(with: models)
mainViewController.collectionView.selectItems(at: [IndexPath.init(item: 0, section: 0)], scrollPosition: .top)

let collectionView = mainViewController.collectionView
collectionView.selectItems(at: [IndexPath.init(item: 18, section: 0)], scrollPosition: .centeredHorizontally)
collectionView.delegate?.collectionView?(collectionView, didSelectItemsAt: [IndexPath.init(item: 18, section: 0)])
}

debugPrint("Loaded \(applications.count) applications.")
Expand Down
6 changes: 3 additions & 3 deletions Sources/Controllers/ApplicationController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -103,11 +103,11 @@ class ApplicationController {
return applications
}

private func loadApplication(at path: URL) throws -> Application {
let infoPath = path.appendingPathComponent("Contents/Info.plist")
private func loadApplication(at url: URL) throws -> Application {
let infoPath = url.appendingPathComponent("Contents/Info.plist")
let propertyList = try infoPlistController.load(at: infoPath)
let preferences = try preferencesController.load(propertyList)
let application = Application(path: path,
let application = Application(url: url,
propertyList: propertyList,
preferences: preferences)
return application
Expand Down
31 changes: 22 additions & 9 deletions Sources/Controllers/SplitViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -42,22 +42,35 @@ class SplitViewController: NSSplitViewController {
verticalDividerLight.belongsToView = view
self.view.addSubview(verticalDividerLight)

let label = Label()
label.textColor = NSColor.windowFrameTextColor
label.stringValue = viewController.title ?? ""
label.alignment = .center
label.belongsToView = view
self.view.addSubview(label)
if let containedViewController = viewController as? SplitViewContainedController {
containedViewController.titlebarView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(containedViewController.titlebarView)
layoutConstraints.append(contentsOf: [
containedViewController.titlebarView.topAnchor.constraint(equalTo: toolbarBackground.topAnchor),
containedViewController.titlebarView.leadingAnchor.constraint(equalTo: toolbarBackground.leadingAnchor),
containedViewController.titlebarView.trailingAnchor.constraint(equalTo: toolbarBackground.trailingAnchor),
containedViewController.titlebarView.bottomAnchor.constraint(equalTo: toolbarBackground.bottomAnchor)
])
} else {
let label = SmallLabel()
label.textColor = NSColor.windowFrameTextColor
label.stringValue = viewController.title ?? ""
label.alignment = .center
label.belongsToView = view
self.view.addSubview(label)

layoutConstraints.append(contentsOf: [
label.centerYAnchor.constraint(equalTo: toolbarBackground.centerYAnchor),
label.centerXAnchor.constraint(equalTo: toolbarBackground.centerXAnchor)
])
}

layoutConstraints.append(contentsOf: [
toolbarBackground.topAnchor.constraint(equalTo: self.view.topAnchor),
toolbarBackground.leadingAnchor.constraint(equalTo: view.leadingAnchor),
toolbarBackground.trailingAnchor.constraint(equalTo: view.trailingAnchor),
toolbarBackground.heightAnchor.constraint(equalToConstant: 38),

label.centerYAnchor.constraint(equalTo: toolbarBackground.centerYAnchor),
label.centerXAnchor.constraint(equalTo: toolbarBackground.centerXAnchor),

contentBackgroundView.topAnchor.constraint(equalTo: self.view.topAnchor),
contentBackgroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
contentBackgroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
Expand Down
1 change: 1 addition & 0 deletions Sources/Controllers/ViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,6 @@ import Cocoa
open class ViewController: NSViewController {
open override func loadView() {
view = NSView()
view.wantsLayer = true
}
}
16 changes: 11 additions & 5 deletions Sources/Factories/ViewControllerFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,17 @@ class ViewControllerFactory {
}

func createApplicationListViewController(with layout: NSCollectionViewFlowLayout) -> ApplicationItemViewController {
let listViewController = ApplicationItemViewController(layout: layout, iconStore: dependencyContainer)
listViewController.view.wantsLayer = true
listViewController.view.layer?.backgroundColor = NSColor.white.cgColor
listViewController.title = Bundle.main.infoDictionary?["CFBundleName"] as? String
let viewController = ApplicationItemViewController(layout: layout, iconStore: dependencyContainer)
viewController.view.wantsLayer = true
viewController.view.layer?.backgroundColor = NSColor.white.cgColor
viewController.title = Bundle.main.infoDictionary?["CFBundleName"] as? String

return listViewController
return viewController
}

func createApplicationDetailViewController() -> ApplicationContainerViewController {
let detailViewController = ApplicationInfoViewController()
let containerViewController = ApplicationContainerViewController(detailViewController: detailViewController)
return containerViewController
}
}
14 changes: 3 additions & 11 deletions Sources/Factories/WindowFactory.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,25 +31,17 @@ class WindowFactory {
sidebarItem.maximumThickness = sidebarItem.minimumThickness
sidebarItem.canCollapse = true

let detailViewController = ViewController()
let detailViewController = viewControllerFactory.createApplicationDetailViewController()
detailViewController.view.wantsLayer = true
detailViewController.view.layer?.backgroundColor = NSColor.windowBackgroundColor.cgColor
detailViewController.title = "Customize"
detailViewController.listViewController = listViewController
listViewController.collectionView.delegate = detailViewController

let detailControllerItem = NSSplitViewItem(viewController: detailViewController)
detailControllerItem.minimumThickness = 320
detailControllerItem.canCollapse = false

let inspectorController = ViewController()
inspectorController.view.wantsLayer = true
inspectorController.view.layer?.backgroundColor = NSColor.white.cgColor

let inspectorControllerItem = NSSplitViewItem(viewController: inspectorController)
inspectorControllerItem.holdingPriority = .init(rawValue: 260)
inspectorControllerItem.minimumThickness = 260
inspectorControllerItem.maximumThickness = 260
inspectorControllerItem.canCollapse = true

let windowController = WindowController(window: window,
with: [sidebarItem, detailControllerItem])

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import Cocoa

class ApplicationActionsViewController: ViewController {
private var layoutConstraints = [NSLayoutConstraint]()

override func viewDidLoad() {
super.viewDidLoad()
view.subviews.forEach { $0.removeFromSuperview() }

NSLayoutConstraint.deactivate(layoutConstraints)
layoutConstraints = []
NSLayoutConstraint.activate(layoutConstraints)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
import Cocoa
import Family

class ApplicationContainerViewController: FamilyViewController,
SplitViewContainedController, NSCollectionViewDelegate {
weak var listViewController: ApplicationItemViewController?

lazy var titleLabel = SmallBoldLabel()
lazy var titlebarView = NSView()

private var layoutConstraints = [NSLayoutConstraint]()

let applicationInfoViewController: ApplicationInfoViewController

init(detailViewController: ApplicationInfoViewController) {
self.applicationInfoViewController = detailViewController
super.init(nibName: nil, bundle: nil)
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}

// MARK: - View lifecycle

override func viewDidLoad() {
super.viewDidLoad()
addChild(applicationInfoViewController,
customInsets: .init(top: 15, left: 15, bottom: 15, right: 15),
height: 120)
addChild(ApplicationActionsViewController(),
customInsets: .init(top: 15, left: 105, bottom: 15, right: 105),
height: 20)
}

// MARK: - Private methods

private func render(_ application: Application) {
applicationInfoViewController.render(application)
NSLayoutConstraint.deactivate(layoutConstraints)
layoutConstraints = []

titlebarView.subviews.forEach { $0.removeFromSuperview() }
titleLabel.stringValue = application.propertyList.bundleName
titleLabel.alignment = .center
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titlebarView.wantsLayer = true
titlebarView.addSubview(titleLabel)

let button = NSButton(title: "Apply changes", target: nil, action: nil)
button.translatesAutoresizingMaskIntoConstraints = false
titlebarView.addSubview(button)

layoutConstraints.append(contentsOf: [
titleLabel.leadingAnchor.constraint(equalTo: titlebarView.leadingAnchor, constant: 10),
titleLabel.trailingAnchor.constraint(equalTo: titlebarView.trailingAnchor, constant: -10),
titleLabel.centerYAnchor.constraint(equalTo: titlebarView.centerYAnchor),
button.centerYAnchor.constraint(equalTo: titlebarView.centerYAnchor),
button.trailingAnchor.constraint(equalTo: titleLabel.trailingAnchor)
])

NSLayoutConstraint.activate(layoutConstraints)
}

// MARK: - NSCollectionViewDelegate

func collectionView(_ collectionView: NSCollectionView, didSelectItemsAt indexPaths: Set<IndexPath>) {
guard let indexPath = indexPaths.first else { return }
guard let listViewController = listViewController else { return }
guard let application = listViewController.model(at: indexPath).data["model"] as? Application else { return }

render(application)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import Cocoa

class ApplicationInfoViewController: ViewController {
private var layoutConstraints = [NSLayoutConstraint]()

lazy var stackView = NSStackView()

func render(_ application: Application) {
view.subviews.forEach { $0.removeFromSuperview() }
stackView.subviews.forEach { $0.removeFromSuperview() }
NSLayoutConstraint.deactivate(layoutConstraints)
layoutConstraints = []

let iconView = NSImageView()
let image = NSWorkspace.shared.icon(forFile: application.url.path)
iconView.image = image

let nameLabel = Label(text: application.propertyList.bundleName)
nameLabel.font = NSFont.boldSystemFont(ofSize: 32)

let horizontalStackView = NSStackView()
horizontalStackView.orientation = .horizontal
horizontalStackView.addArrangedSubview(iconView)
horizontalStackView.addArrangedSubview(nameLabel)

stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.orientation = .vertical
stackView.alignment = .leading
stackView.distribution = .fillProportionally
stackView.addArrangedSubview(horizontalStackView)

stackView.addArrangedSubview(createVerticalStackView(with: [
BoldLabel(text: "Version:"),
Label(text: application.propertyList.versionString),
BoldLabel(text: "Bundle identifier:"),
Label(text: application.propertyList.bundleIdentifier)]))

stackView.addArrangedSubview(createVerticalStackView(with: [BoldLabel(text: "Location:"),
Label(text: application.url.path)]))
view.addSubview(stackView)
layoutConstraints = [
stackView.topAnchor.constraint(equalTo: view.topAnchor),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: view.bottomAnchor)
]
NSLayoutConstraint.activate(layoutConstraints)
}

func createVerticalStackView(with views: [NSView]) -> NSStackView {
let stackView = NSStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.orientation = .horizontal
stackView.alignment = .firstBaseline
stackView.spacing = 5
views.forEach { stackView.addArrangedSubview($0) }
return stackView
}
}
File renamed without changes.
File renamed without changes.
File renamed without changes.
4 changes: 2 additions & 2 deletions Sources/Models/Application.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import Foundation

struct Application {
let path: URL
struct Application: Hashable {
let url: URL
let propertyList: InfoPropertyList
let preferences: Preferences
}
4 changes: 2 additions & 2 deletions Sources/Models/InfoPropertyList.swift
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import Foundation

enum InfoPropertyListKey: String {
enum InfoPropertyListKey: String, Hashable {
case buildVersion = "CFBundleVersion"
case bundleIdentifier = "CFBundleIdentifier"
case bundleName = "CFBundleName"
Expand All @@ -10,7 +10,7 @@ enum InfoPropertyListKey: String {
case versionString = "CFBundleShortVersionString"
}

struct InfoPropertyList {
struct InfoPropertyList: Hashable {
let buildVersion: String
let bundleIdentifier: String
let bundleName: String
Expand Down
2 changes: 1 addition & 1 deletion Sources/Models/Preferences.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import Foundation

struct Preferences {
struct Preferences: Hashable {
let path: URL
}
5 changes: 5 additions & 0 deletions Sources/Protocols/SplitViewContainedController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import Cocoa

protocol SplitViewContainedController {
var titlebarView: NSView { get }
}
Loading

0 comments on commit 4db977d

Please sign in to comment.