Skip to content

Commit

Permalink
Add Initial Node Expand strategy
Browse files Browse the repository at this point in the history
  • Loading branch information
varkrishna committed Nov 2, 2023
1 parent c2cbf73 commit 686e500
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,13 @@ public struct JSONViewerFontConfiguration {
}

}


public enum InitialNodeExpandStrategy {
case none
case root
case all

// case uptoLevel(Int)
// case arrayUptoLevel(Int)
}
27 changes: 21 additions & 6 deletions Sources/JSONViewer/JSONNodeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,22 @@ import SwiftUI
public struct JSONNodeView: View {
let node: JSONNode
let level: Int
private var initialNodeExpandStategy: InitialNodeExpandStrategy = .root
@Binding var fontConfiguration: JSONViewerFontConfiguration
@State var expandedNodes: [String: Bool]

internal init(node: JSONNode, level: Int, expandedNodes: [String: Bool], fontConfiguration: Binding<JSONViewerFontConfiguration>) {
internal init(node: JSONNode, level: Int, fontConfiguration: Binding<JSONViewerFontConfiguration>, initialNodeExpandStategy: InitialNodeExpandStrategy) {
self.node = node
self.level = level
self._expandedNodes = State(initialValue: expandedNodes)
self._fontConfiguration = fontConfiguration
self.initialNodeExpandStategy = initialNodeExpandStategy
if initialNodeExpandStategy == .root && level == 0 {
_expandedNodes = State(initialValue: ["Root": true])
} else if initialNodeExpandStategy == .all {
_expandedNodes = State(initialValue: [node.key: true])
} else {
_expandedNodes = State(initialValue: [:])
}
}

public var body: some View {
Expand All @@ -37,7 +45,7 @@ public struct JSONNodeView: View {
Circle()
.fill(.white)
.frame(width: 8, height: 8)
HStack(spacing: 0) {
HStack(alignment: .top, spacing: 0) {
Text("\(node.key)")
.font(fontConfiguration.keyFont)
Text(":")
Expand Down Expand Up @@ -92,8 +100,8 @@ public struct JSONNodeView: View {
HStack() {
JSONNodeView(node: childNode,
level: level + 1,
expandedNodes: [String : Bool](),
fontConfiguration: self.$fontConfiguration)
fontConfiguration: self.$fontConfiguration,
initialNodeExpandStategy: self.initialNodeExpandStategy)
}
}
}
Expand All @@ -119,9 +127,16 @@ public struct JSONNodeView: View {
.frame(maxWidth: .infinity, maxHeight: .infinity)
.buttonStyle(PlainButtonStyle())

if self.expandedNodes[node.key] ?? false {
if shouldShowSuccessorView() {
nodeSuccessorView()
}
}
}

func shouldShowSuccessorView() -> Bool {
if let value = self.expandedNodes[node.key] {
return value
}
return false
}
}
16 changes: 8 additions & 8 deletions Sources/JSONViewer/JSONViewer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -3,28 +3,28 @@ import SwiftUI
public struct JSONViewer: View {
@Binding var fontConfiguration: JSONViewerFontConfiguration
private let rootNode: JSONNode
private let expandedNodes: [String: Bool]
private var initialNodeExpandStategy: InitialNodeExpandStrategy = .root

public init(rootNode: JSONNode, isRootExpanded: Bool = true) {
public init(rootNode: JSONNode, initialNodeExpandStategy: InitialNodeExpandStrategy = .root) {
self.rootNode = rootNode
self.expandedNodes = isRootExpanded ? ["Root": true] : [:]
self.initialNodeExpandStategy = initialNodeExpandStategy
self._fontConfiguration = Binding.constant(JSONViewerFontConfiguration())
}

public init(rootNode: JSONNode, fontConfiguration: Binding<JSONViewerFontConfiguration>, isRootExpanded: Bool = true) {
public init(rootNode: JSONNode, fontConfiguration: Binding<JSONViewerFontConfiguration>, initialNodeExpandStategy: InitialNodeExpandStrategy = .root) {
self.rootNode = rootNode
self.expandedNodes = isRootExpanded ? ["Root": true] : [:]
self.initialNodeExpandStategy = initialNodeExpandStategy
self._fontConfiguration = fontConfiguration
}

public var body: some View {
HStack {
VStack {
ScrollView {
JSONNodeView(node: rootNode,
JSONNodeView(node: rootNode,
level: 0,
expandedNodes: self.expandedNodes,
fontConfiguration: $fontConfiguration)
fontConfiguration: $fontConfiguration,
initialNodeExpandStategy: self.initialNodeExpandStategy)
}
.scrollIndicators(.hidden)
Spacer()
Expand Down
49 changes: 49 additions & 0 deletions Sources/JSONViewer/NodeSortingStrategies.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
//
// File.swift
//
//
// Created by krishna varshney on 25/10/23.
//

import Foundation

public enum SortingStrategy {
case ascending
case descending
case none
}

class SortedDictionary: Sequence, IteratorProtocol {
private let source: Dictionary<String, Any>
private let strategy: SortingStrategy
private var idx = -1

private lazy var sortedData: ([Dictionary<String, Any>.Element]) = {
switch strategy {
case .ascending:
return source.sorted(by: { $0.key < $1.key })
case .descending:
return source.sorted(by: { $0.key > $1.key })
case .none:
return source.map({$0})
}

}()

internal init(source: Dictionary<String, Any>, strategy: SortingStrategy) {
self.source = source
self.strategy = strategy
}

func makeIterator() -> SortedDictionary {
return self
}

func next() -> (String, Any)? {
idx += 1
guard sortedData.indices.contains(idx) else {
return nil
}
return (sortedData[idx].key, sortedData[idx].value)
}
}
15 changes: 8 additions & 7 deletions Sources/JSONViewer/StringExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@
import Foundation

public extension String {
var jsonNode: JSONNode? {
func jsonNode(sortingStrategy: SortingStrategy = .none) -> JSONNode? {
if let jsonData = self.data(using: .utf8) {
do {
let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
if let jsonDict = jsonObject as? [String: Any] {
return self.createNode(key: "Root", value: jsonDict)
return self.createNode(key: "Root", value: jsonDict, sortingStrategy: sortingStrategy)
} else if let jsonArray = jsonObject as? [[String: Any]] {
return self.createNode(key: "Root", value: jsonArray)
return self.createNode(key: "Root", value: jsonArray, sortingStrategy: sortingStrategy)
} else {
return nil
}
Expand All @@ -26,18 +26,19 @@ public extension String {
return nil
}

private func createNode(key: String, value: Any) -> JSONNode {
private func createNode(key: String, value: Any, sortingStrategy: SortingStrategy) -> JSONNode {
var children: [JSONNode] = []
var type: JSONNodeType = .other
if let dict = value as? [String: Any] {
type = .object
for (key, value) in dict {
children.append(createNode(key: key, value: value))
let sortedDict = SortedDictionary(source: dict, strategy: sortingStrategy)
for (key, value) in sortedDict {
children.append(createNode(key: key, value: value, sortingStrategy: sortingStrategy))
}
} else if let array = value as? [Any] {
type = .array
for (index, item) in array.enumerated() {
children.append(createNode(key: "\(index)", value: item))
children.append(createNode(key: "\(index)", value: item, sortingStrategy: sortingStrategy))
}
} else {
children = []
Expand Down

0 comments on commit 686e500

Please sign in to comment.