Skip to content

Commit

Permalink
Refactor icon loading
Browse files Browse the repository at this point in the history
- Simplify the icon loading
- Use paths instead of a model to load icons from disk
- Add `PathFinderController` to make sure that we have all the correct
  application paths inside the application commands
  • Loading branch information
zenangst committed Dec 16, 2020
1 parent 072641e commit c20d68f
Show file tree
Hide file tree
Showing 14 changed files with 73 additions and 209 deletions.
5 changes: 4 additions & 1 deletion App/Sources/Application/Saloon.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ class Saloon: ViewKitStore, MenubarControllerDelegate {
private var menuBarController: MenubarController?
private var subscriptions = Set<AnyCancellable>()
private var loaded: Bool = false
private let pathFinderController = PathFinderController()

@Published var state: ApplicationState = .launching(LaunchView())

Expand All @@ -64,7 +65,7 @@ class Saloon: ViewKitStore, MenubarControllerDelegate {
return
}

let groups = try storageController.load()
var groups = try storageController.load()
let groupsController = Self.factory.groupsController(groups: groups)
let hotKeyController = try? Self.factory.hotkeyController()
let coreController = Self.factory.coreController(
Expand All @@ -73,6 +74,8 @@ class Saloon: ViewKitStore, MenubarControllerDelegate {
hotKeyController: hotKeyController
)

groups = pathFinderController.patch(groups, applications: coreController.installedApplications)

self.coreController = coreController

let context = FeatureFactory(coreController: coreController).featureContext(
Expand Down
36 changes: 36 additions & 0 deletions LogicFramework/Sources/Applications/PathFinderController.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import Foundation
import ModelKit

/// Make sure that all current path reference are correct for the persisted groups
public class PathFinderController {
public init() {}

public func patch(_ groups: [Group], applications: [Application]) -> [Group] {
var appDictionary = [String: Application]()
for app in applications {
appDictionary[app.bundleIdentifier] = app
}

var groups = groups
for (gOffset, group) in groups.enumerated() {
for (wOffset, workflow) in group.workflows.enumerated() {
for (cOffset, command) in workflow.commands.enumerated() {

if case .application(let appCommand) = command,
let application = appDictionary[appCommand.application.bundleIdentifier],
application.path != appCommand.application.path {
let newCommand = Command.application(.init(
id: appCommand.id,
name: appCommand.name,
application: application
))

groups[gOffset].workflows[wOffset].commands[cOffset] = newCommand
}
}
}
}

return groups
}
}
1 change: 1 addition & 0 deletions LogicFramework/Sources/Logic/CoreController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ public final class CoreController: NSObject, CoreControlling,
let workflowController: WorkflowControlling
let workspace: WorkspaceProviding
var cache = [String: Int]()

private(set) public var installedApplications = [Application]()

public var groups: [Group] { return groupsController.groups }
Expand Down
17 changes: 5 additions & 12 deletions ViewKit/Sources/Extensions/Command+Extensions.swift
Original file line number Diff line number Diff line change
@@ -1,23 +1,16 @@
import ModelKit

extension Command {
var icon: Icon {
let icon: Icon
var icon: String {
switch self {
case .application(let applicationCommand):
icon = Icon(identifier: applicationCommand.application.bundleIdentifier,
path: applicationCommand.application.path)
return applicationCommand.application.path
case .script:
icon = Icon(identifier: "com.apple.ScriptEditor2",
path: "/System/Applications/Utilities/Script Editor.app")
return "/System/Applications/Utilities/Script Editor.app"
case .keyboard:
icon = Icon(identifier: "com.apple.preference.keyboard",
path: "/System/Library/PreferencePanes/Keyboard.prefPane")
return "/System/Library/PreferencePanes/Keyboard.prefPane"
case .open:
icon = Icon(identifier: "com.apple.finder",
path: "/System/Library/CoreServices/Finder.app")
return "/System/Library/CoreServices/Finder.app"
}

return icon
}
}
150 changes: 0 additions & 150 deletions ViewKit/Sources/Helpers/IconController.swift

This file was deleted.

17 changes: 14 additions & 3 deletions ViewKit/Sources/Helpers/IconLoader.swift
Original file line number Diff line number Diff line change
@@ -1,7 +1,18 @@
import Cocoa
import SwiftUI

public protocol IconLoader: ObservableObject where ObjectWillChangePublisher.Output == Void {
associatedtype State
class IconLoader: ObservableObject {
@Published public private(set) var image: Image?

var icon: State { get }
func load(_ path: String) {
image = Image(nsImage: NSWorkspace.shared.icon(forFile: path))
}

func cancel() {
image = nil
}

deinit {
cancel()
}
}
5 changes: 1 addition & 4 deletions ViewKit/Sources/Views/Commands/AppleScriptView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@ struct AppleScriptView: View {
var body: some View {
HStack {
ZStack {
IconView(icon: Icon(
identifier: "script-editor-file",
path: "/System/Applications/Utilities/Script Editor.app/Contents/Resources/script-editor-dummy.scptd")
)
IconView(path: "/System/Applications/Utilities/Script Editor.app/Contents/Resources/script-editor-dummy.scptd")
PlayArrowView()
}.frame(width: 32, height: 32)

Expand Down
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/Commands/ApplicationView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct ApplicationView: View {
var body: some View {
HStack {
if case .application(let model) = command {
IconView(icon: Icon(identifier: model.application.bundleIdentifier, path: model.application.path))
IconView(path: model.application.path)
.frame(width: 32, height: 32)
}
VStack(alignment: .leading, spacing: 2) {
Expand Down
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/Commands/KeyboardCommandView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ struct KeyboardCommandView: View {
var body: some View {
HStack {
ZStack {
IconView(icon: Icon(identifier: "keyboard-shortcut", path: "/System/Library/PreferencePanes/Keyboard.prefPane"))
IconView(path: "/System/Library/PreferencePanes/Keyboard.prefPane")
.frame(width: 32, height: 32)
}
VStack(alignment: .leading, spacing: 0) {
Expand Down
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/Commands/OpenCommandView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct OpenCommandView: View {
HStack {
ZStack {
if case .open(let openCommand) = command {
IconView(icon: Icon(identifier: openCommand.path, path: openCommand.application?.path ?? ""))
IconView(path: openCommand.application?.path ?? "")
}
}.frame(width: 32, height: 32)
VStack(alignment: .leading, spacing: 0) {
Expand Down
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/Commands/ShellScriptView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ struct ShellScriptView: View {
var body: some View {
HStack {
ZStack {
IconView(icon: Icon(identifier: "shell-script-file", path: "/System/Applications/Utilities/Terminal.app"))
IconView(path: "/System/Applications/Utilities/Terminal.app")
.frame(width: 32, height: 32)
PlayArrowView()
}
Expand Down
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/EditGroup/EditGroup.swift
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ private extension EditGroup {
ForEach(installedApplications.filter({ bundleIdentifiers.contains($0.bundleIdentifier) }), id: \.id) { application in
VStack(spacing: 0) {
HStack {
IconView(icon: Icon(identifier: application.bundleIdentifier, path: application.path))
IconView(path: application.path)
Text(application.displayName)
Spacer()
Button("-", action: {
Expand Down
39 changes: 6 additions & 33 deletions ViewKit/Sources/Views/Shared/IconView.swift
Original file line number Diff line number Diff line change
@@ -1,38 +1,13 @@
import SwiftUI

struct Icon: Hashable, Identifiable {
let identifier: String
let path: String
let id: String

init(identifier: String, path: String) {
self.identifier = identifier
self.path = path
self.id = identifier + path
}
}

struct IconView: View {
@ObservedObject var iconLoader = IconController()

let icon: Icon

init(icon: Icon) {
self.icon = icon
iconLoader.preLoadIcon(identifier: icon.identifier, at: icon.path, size: CGSize(width: 32, height: 32))
}
let path: String
@StateObject var iconLoader = IconLoader()

var body: some View {
ZStack {
if iconLoader.icon != nil {
Image(nsImage: iconLoader.icon!)
}
}.onAppear {
if iconLoader.icon == nil {
iconLoader.loadIcon(identifier: icon.identifier, at: icon.path, size: CGSize(width: 32, height: 32))
}
}
.frame(width: 32, height: 32)
iconLoader.image
}.onAppear { iconLoader.load(path) }
}
}

Expand All @@ -43,10 +18,8 @@ struct IconView_Previews: PreviewProvider, TestPreviewProvider {

static var testPreview: some View {
Group {
IconView(icon: Icon(identifier: "com.apple.Finder",
path: "/System/Library/CoreServices/Finder.app"))
IconView(icon: Icon(identifier: "keyboard",
path: "/System/Library/PreferencePanes/Keyboard.prefPane"))
IconView(path: "/System/Library/CoreServices/Finder.app")
IconView(path: "/System/Library/PreferencePanes/Keyboard.prefPane")
}.frame(width: 48, height: 48)
}
}
2 changes: 1 addition & 1 deletion ViewKit/Sources/Views/WorkflowList/WorkflowListView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ private extension WorkflowListView {
? workflow.commands.count > 1 ? 0.9 + ( 0.05 * cgIndex) : 1.0
: 1.0

IconView(icon: command.icon).frame(width: 48, height: 48)
IconView(path: command.icon).frame(width: 48, height: 48)
.scaleEffect(scale, anchor: .center)
.offset(x: isHovering ? multiplier : 0,
y: isHovering ? multiplier : 0)
Expand Down

0 comments on commit c20d68f

Please sign in to comment.