Skip to content

Commit

Permalink
Refactored sidebar for improved perf and reusability (#490)
Browse files Browse the repository at this point in the history
  • Loading branch information
ellbosch authored Oct 28, 2024
1 parent 69fae30 commit c881445
Show file tree
Hide file tree
Showing 79 changed files with 2,325 additions and 4,690 deletions.
74 changes: 26 additions & 48 deletions Stitch.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
{
"originHash" : "87be221b3fbded1c8027b1ce26671216264e4726379ed9409d52282eb1aab675",
"pins" : [
{
"identity" : "audiokit",
Expand Down Expand Up @@ -67,17 +66,7 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/StitchDesign/StitchSchemaKit",
"state" : {
"revision" : "0e6458824efb1400aa1e158f165bb9035c703d06",
"version" : "26.0.0"
}
},
{
"identity" : "stitchviewkit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/StitchDesign/StitchViewKit.git",
"state" : {
"revision" : "d8eaaf3e7522038e16f963a332c505a105ecbde5",
"version" : "1.0.3"
"revision" : "6e0c9363337ddaba01afbc51fb27d143b18f6cca"
}
},
{
Expand Down Expand Up @@ -144,5 +133,5 @@
}
}
],
"version" : 3
"version" : 2
}
26 changes: 13 additions & 13 deletions Stitch/App/Logging/LogUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,17 +18,17 @@ enum LoggingAction: Equatable {
case none, logToServer, fatal
}

struct LogToServer: AppEvent {
let message: String

// TODO: write state + message + device info to server (if online)
func handle(state: AppState) -> AppResponse {
.noChange
}
}
//struct LogToServer: AppEvent {
// let message: String
//
// // TODO: write state + message + device info to server (if online)
// func handle(state: AppState) -> AppResponse {
// .noChange
// }
//}

// For debug printing from within SwiftUI views
func log(_ message: String, _ loggingAction: LoggingAction = .none) {
func log(_ message: Any, _ loggingAction: LoggingAction = .none) {
#if DEBUG || DEV_DEBUG
print("** \(message)")

Expand All @@ -37,14 +37,14 @@ func log(_ message: String, _ loggingAction: LoggingAction = .none) {
return
case .fatal:
#if DEV_DEBUG
fatalError("FATAL:" + message)
fatalError("FATAL: \(message)")
#endif
case .logToServer:
print("HAD MAJOR ERROR: \(message)")

DispatchQueue.main.async {
dispatch(LogToServer(message: message))
}
// DispatchQueue.main.async {
// dispatch(LogToServer(message: message))
// }
}
#endif
}
Expand Down
34 changes: 4 additions & 30 deletions Stitch/App/Shortcut/ProjectsHomeCommands.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,45 +23,19 @@ struct ProjectsHomeCommands: Commands {
var layersActivelySelected: Bool {
self.graph?.hasActivelySelectedLayers ?? false
}

var selections: SidebarSelectionState? {
self.graph?.sidebarSelectionState
}

var graph: GraphState? {
store.currentDocument?.visibleGraph
}

var groups: SidebarGroupsDict? {
graph?.getSidebarGroupsDict()
}

var layerNodes: LayerNodesForSidebarDict? {
if let graph = graph {
return LayerNodesForSidebarDict.fromLayerNodesDict(
nodes: graph.layerNodes,
orderedSidebarItems: graph.orderedSidebarLayers)
}
return nil
}

var ungroupButtonEnabled: Bool {
if let selections = selections,
let layerNodes = layerNodes {
return canUngroup(selections.primary, nodes: layerNodes)
}
return false
self.graph?.layersSidebarViewModel.canUngroup() ?? false
}

var groupButtonEnabled: Bool {
if let selections = selections,
let groups = groups {
return selections.nonEmptyPrimary.map { canBeGrouped($0, groups: groups) } ?? false
}
return false
self.graph?.layersSidebarViewModel.canBeGrouped() ?? false
}


var textFieldFocused: Bool {
let k = activeReduxFocusedField.isDefined || focusedField.isDefined
// log("ProjectsHomeCommands: activeReduxFocusedField: \(activeReduxFocusedField)")
Expand Down Expand Up @@ -315,7 +289,7 @@ struct ProjectsHomeCommands: Commands {
// Disabled if no layers are actively selected
disabled: !layersActivelySelected || !groupButtonEnabled) {
// deletes both selected nodes and selected comments
dispatch(SidebarGroupCreated())
self.graph?.layersSidebarViewModel.sidebarGroupCreated()
}

SwiftUIShortcutView(title: "Ungroup Layers",
Expand All @@ -325,7 +299,7 @@ struct ProjectsHomeCommands: Commands {
disabled: !layersActivelySelected || !ungroupButtonEnabled) {
// disabled: !layersActivelySelected) {
// deletes both selected nodes and selected comments
dispatch(SidebarGroupUncreated())
self.graph?.layersSidebarViewModel.sidebarGroupUncreated()
}

} // replacing: .pasteboard
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ import StitchSchemaKit

/// View controller abstraction for better handling of gestures. Fixes problem where a gesture
/// may not work across many different views.
class GestureHostingController<T: View>: StitchHostingController<T> {
final class GestureHostingController<T: View>: StitchHostingController<T> {
weak var delegate: UIGestureRecognizerDelegate?
}
2 changes: 1 addition & 1 deletion Stitch/Graph/LayerInspector/LayerInspectorActions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import StitchSchemaKit
extension GraphDelegate {
// TODO: cache these for perf
var nonEditModeSelectedLayerInLayerSidebar: NodeId? {
self.sidebarSelectionState.inspectorFocusedLayers.focused.first?.id
self.sidebarSelectionState.inspectorFocusedLayers.focused.first
}

// TODO: cache these for perf
Expand Down
8 changes: 4 additions & 4 deletions Stitch/Graph/LayerInspector/LayerInspectorView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -315,13 +315,13 @@ extension GraphState {
return nil
}

var selectedLayers = self.sidebarSelectionState.inspectorFocusedLayers.focused
var selectedLayers = self.layersSidebarViewModel.inspectorFocusedLayers.focused

#if DEV_DEBUG
// For debug
if selectedLayers.isEmpty,
let layer = self.layerNodes.keys.first {
selectedLayers = .init([.init(layer)])
selectedLayers = .init([layer])
}
#endif

Expand All @@ -338,15 +338,15 @@ extension GraphState {
return (header: "Multiselect",
// node: nil,
// TODO: is this bad? grabbing
node: firstLayer.asNodeId,
node: firstLayer,
inputs: inputs,
outputs: []) // TODO: multiselect for outputs

}

// else had 0 or 1 layers selected:
else {
guard let inspectedLayerId = self.sidebarSelectionState.inspectorFocusedLayers.focused.first?.id,
guard let inspectedLayerId = self.layersSidebarViewModel.inspectorFocusedLayers.focused.first,
let node = self.getNodeViewModel(inspectedLayerId),
let layerNode = node.layerNode else {
// log("LayerInspectorView: No inspector-focused layers?: \(self.sidebarSelectionState.inspectorFocusedLayers)")
Expand Down
2 changes: 1 addition & 1 deletion Stitch/Graph/LayerInspector/LayerMultiselect.swift
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ extension LayerInputPort {
let selectedLayers = graph.sidebarSelectionState.inspectorFocusedLayers

let observers: [LayerInputObserver] = selectedLayers.focused.compactMap {
if let layerNode = graph.getNodeViewModel($0.id)?.layerNode {
if let layerNode = graph.getNodeViewModel($0)?.layerNode {
let observer: LayerInputObserver = layerNode[keyPath: self.layerNodeKeyPath]
return observer
}
Expand Down
6 changes: 6 additions & 0 deletions Stitch/Graph/Model/SchemaVersions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,8 @@ extension StitchDocumentVersion {
return StitchDocument_V25.StitchDocument.self
case ._V26:
return StitchDocument_V26.StitchDocument.self
case ._V27:
return StitchDocument_V27.StitchDocument.self
}
}
}
Expand All @@ -210,6 +212,8 @@ extension StitchSystemVersion {
return StitchSystem_V25.StitchSystem.self
case ._V26:
return StitchSystem_V26.StitchSystem.self
case ._V27:
return StitchSystem_V27.StitchSystem.self
}
}
}
Expand All @@ -224,6 +228,8 @@ extension StitchComonentVersion {
return StitchComponent_V25.StitchComponent.self
case ._V26:
return StitchComponent_V26.StitchComponent.self
case ._V27:
return StitchComponent_V27.StitchComponent.self
}
}
}
Expand Down
60 changes: 1 addition & 59 deletions Stitch/Graph/Node/Layer/Type/GroupLayerNode.swift
Original file line number Diff line number Diff line change
Expand Up @@ -134,62 +134,4 @@ struct GroupLayerNode: LayerNodeDefinition {

extension LayerSize {
static let defaultLayerGroupSize = LayerSize(width: .fill, height: .fill)
}

extension GraphState {
// Creates just the LayerNode itself;
// does not add to SidebarGroups state etc.

// When we create a GroupLayerNode, we must:
// (1) determine its position and size
// based on its children's sizes and positions; and
// (2) update the children's positions
// ASSUMES: "Fit to Selection" mode.
@MainActor
func createGroupLayerNode(groupLayerData: SidebarLayerData,
// position of layer node on graph
position: CGPoint,
// z-height of layer node on graph
zIndex: ZIndex) -> NodeViewModel? {
guard let children = groupLayerData.children else {
fatalErrorIfDebug()
return nil
}

let selectedNodes = children
.flatMap { $0.allElementIds }
.toSet

let parentSize: CGSize = self.getParentSizeForSelectedNodes(selectedNodes: selectedNodes)

// determine sise and position of group layer node,
// plus how much to adjust the position of any children inside.
let layerGroupFit = self.getLayerGroupFit(
selectedNodes,
parentSize: parentSize)

self.adjustGroupChildrenToLayerFit(
layerGroupFit,
selectedNodes)

let newNode = Layer.group.graphNode.createViewModel(id: groupLayerData.id,
position: position,
zIndex: zIndex,
graphDelegate: self)
newNode.layerNode?.sizePort.updatePortValues([.size(layerGroupFit.size)])
newNode.layerNode?.positionPort.updatePortValues([.position(layerGroupFit.position)])

newNode.graphDelegate = self

// Update selected nodes to report to new group node
selectedNodes.forEach { nodeId in
guard let layerNode = self.getNodeViewModel(nodeId)?.layerNode else {
log("createGroupLayerNode: no node found")
return
}
layerNode.layerGroupId = newNode.id
}

return newNode
}
}
}
9 changes: 0 additions & 9 deletions Stitch/Graph/Node/Layer/Util/LayerGroups.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,6 @@ import Foundation
import SwiftUI
import StitchSchemaKit

// Find the parent, if any, for this layer node.
func findGroupLayerParentForLayerNode(_ nodeId: LayerNodeId,
_ groups: SidebarGroupsDict) -> LayerNodeId? {

groups.first { (_: LayerNodeId, value: LayerIdList) in
value.contains(nodeId)
}?.key
}

extension GraphState {
// Assumes:
// - all selected nodes have either same parent or no parent ('top level')
Expand Down
6 changes: 2 additions & 4 deletions Stitch/Graph/Node/Layer/Util/LayerNodeEntityUtils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -117,8 +117,7 @@ extension LayerNodeEntity {
materialThicknessPort: LayerInputEntity = .empty,
deviceAppearancePort: LayerInputEntity = .empty,
hasSidebarVisibility: Bool,
layerGroupId: NodeId?,
isExpandedInSidebar: Bool?) {
layerGroupId: NodeId?) {

let outputsCount = layer.layerGraphNode.rowDefinitions(for: nil).outputs.count

Expand Down Expand Up @@ -240,7 +239,6 @@ extension LayerNodeEntity {
materialThicknessPort: materialThicknessPort,

hasSidebarVisibility: hasSidebarVisibility,
layerGroupId: layerGroupId,
isExpandedInSidebar: isExpandedInSidebar)
layerGroupId: layerGroupId)
}
}
2 changes: 1 addition & 1 deletion Stitch/Graph/Node/Layer/Util/LayerNodeId.swift
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ extension LayerNodeId {
}

var asItemId: SidebarListItemId {
SidebarListItemId(id)
self.asNodeId
}

var asNodeId: NodeId {
Expand Down
12 changes: 1 addition & 11 deletions Stitch/Graph/Node/Layer/ViewModel/LayerNodeViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -165,8 +165,6 @@ final class LayerNodeViewModel {
}
}
}

var isExpandedInSidebar: Bool?

init(from schema: LayerNodeEntity) {

Expand All @@ -180,7 +178,6 @@ final class LayerNodeViewModel {
self.layer = schema.layer
self.hasSidebarVisibility = schema.hasSidebarVisibility
self.layerGroupId = schema.layerGroupId
self.isExpandedInSidebar = schema.isExpandedInSidebar

self.outputPorts = rowDefinitions
.createOutputLayerPorts(schema: schema,
Expand Down Expand Up @@ -412,8 +409,7 @@ extension LayerNodeViewModel: SchemaObserver {
var schema = LayerNodeEntity(nodeId: self.id,
layer: layer,
hasSidebarVisibility: hasSidebarVisibility,
layerGroupId: layerGroupId,
isExpandedInSidebar: self.isExpandedInSidebar)
layerGroupId: layerGroupId)

// Only encode keypaths used by this layer
self.layer.layerGraphNode.inputDefinitions.forEach { inputType in
Expand Down Expand Up @@ -561,12 +557,6 @@ extension LayerNodeViewModel {
changedPortId: changedPortId)
}
}

var visibilityStatusIcon: String {
self.hasSidebarVisibility
? SIDEBAR_VISIBILITY_STATUS_VISIBLE_ICON
: SIDEBAR_VISIBILITY_STATUS_HIDDEN_ICON
}
}

extension Layer {
Expand Down
3 changes: 1 addition & 2 deletions Stitch/Graph/Node/Model/GraphCopyable.swift
Original file line number Diff line number Diff line change
Expand Up @@ -191,8 +191,7 @@ extension LayerNodeEntity: GraphCopyable {
var newSchema = LayerNodeEntity(nodeId: newId,
layer: self.layer,
hasSidebarVisibility: self.hasSidebarVisibility,
layerGroupId: mappableData.get(self.layerGroupId),
isExpandedInSidebar: self.isExpandedInSidebar)
layerGroupId: mappableData.get(self.layerGroupId))

// Iterate through layer inputs
self.layer.layerGraphNode.inputDefinitions.forEach {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ enum FocusedUserEditField: Equatable, Hashable {
any, // default option
llmRecordingModal,
stitchAIPromptModal,
sidebarLayerTitle(LayerNodeId)
sidebarLayerTitle(String)

var getTextFieldLayerInputEdit: PreviewCoordinate? {
switch self {
Expand Down
Loading

0 comments on commit c881445

Please sign in to comment.