Skip to content

Commit e7af58b

Browse files
committed
go with observed object
1 parent bed0ea7 commit e7af58b

File tree

5 files changed

+63
-43
lines changed

5 files changed

+63
-43
lines changed

yCHM/CHMFile.swift

+8-7
Original file line numberDiff line numberDiff line change
@@ -9,18 +9,19 @@ import Foundation
99

1010
class CHMFile {
1111
let fd: OpaquePointer
12-
let items: [CHMUnit]
13-
let index: [CHMUnit]
14-
let tree: [CHMUnit]
12+
let items: CHMUnit
13+
let index: CHMUnit
14+
let tree: CHMUnit
1515

1616
init(filename: String) {
1717
fd = chm_open(filename)
18-
items = listCHMUnit(fd, filter: CHM_ENUMERATE_ALL).0
19-
let hhcPath = items.first(where: {$0.path.lowercased().hasSuffix(".hhc")})?.path
18+
let allItems = listCHMUnit(fd, filter: CHM_ENUMERATE_ALL).0
19+
items = CHMUnit(name: "", path: "", children: allItems, parent: nil)
20+
let hhcPath = allItems.first(where: {$0.path.lowercased().hasSuffix(".hhc")})?.path
2021
// if hhc == nil
2122
let hhcData = getUrlContent(fd, path: hhcPath!)
2223
tree = parseIndex(hhcData)
23-
let hhkPath = items.first(where: {$0.path.lowercased().hasSuffix(".hhk")})?.path
24+
let hhkPath = allItems.first(where: {$0.path.lowercased().hasSuffix(".hhk")})?.path
2425
// if hhk == nil
2526
let hhkData = getUrlContent(fd, path: hhkPath!)
2627
index = parseIndex(hhkData)
@@ -31,7 +32,7 @@ class CHMFile {
3132
}
3233

3334
func entryPoint () -> CHMUnit {
34-
var item = tree[0]
35+
var item = tree.children![0]
3536
while item.children?[0] != nil {
3637
item = item.children![0]
3738
}

yCHM/ContentView.swift

+11-11
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,9 @@ struct ContentView: View {
1515
@State var selector: selectorType = .tree
1616
@State var searchText: String = ""
1717

18-
@State var index: [CHMUnitFiltable] = []
19-
@State var tree: [CHMUnitFiltable] = []
20-
@State var object: [CHMUnitFiltable] = []
18+
@StateObject var index: CHMUnitFiltable = CHMUnitFiltable()
19+
@StateObject var tree: CHMUnitFiltable = CHMUnitFiltable()
20+
@StateObject var object: CHMUnitFiltable = CHMUnitFiltable()
2121

2222
let docPicker = DocPicker()
2323

@@ -43,9 +43,9 @@ struct ContentView: View {
4343
}).disabled(selector == .object)
4444
}
4545
switch selector {
46-
case .flat: TreeView(items: $index, textFilter: $searchText, selected: $location.unit)
47-
case .tree: TreeView(items: $tree, textFilter: $searchText, selected: $location.unit)
48-
case .object: TreeView(items: $object, textFilter: $searchText, selected: $location.unit)
46+
case .flat: TreeView(items: index, textFilter: $searchText, selected: $location.unit)
47+
case .tree: TreeView(items: tree, textFilter: $searchText, selected: $location.unit)
48+
case .object: TreeView(items: object, textFilter: $searchText, selected: $location.unit)
4949
}
5050
}
5151
.frame(minWidth: 100, idealWidth: 200, maxWidth: 200, minHeight: /*@START_MENU_TOKEN@*/0/*@END_MENU_TOKEN@*/, idealHeight: .infinity, maxHeight: .infinity, alignment: .center)
@@ -67,9 +67,9 @@ struct ContentView: View {
6767
func fileOpened(_ filename: String?) {
6868
if filename != nil {
6969
chm = CHMFile(filename: filename!)
70-
index = chm!.index.map({CHMUnitFiltable(unit: $0)})
71-
tree = chm!.tree.map({CHMUnitFiltable(unit: $0)})
72-
object = chm!.items.map({CHMUnitFiltable(unit: $0)})
70+
index.load(unit: chm!.index)
71+
tree.load(unit: chm!.tree)
72+
object.load(unit: chm!.items)
7373
location.urlCallback = chm!.urlCallback
7474
location.unit = CHMUnitFiltable(unit: chm!.entryPoint())
7575
}
@@ -80,13 +80,13 @@ struct ContentView_Previews: PreviewProvider {
8080
static var previews: some View {
8181
ContentView(
8282
location: CHMLocation(),
83-
tree: [CHMUnitFiltable(unit: CHMUnit(path: "/", children: [
83+
tree: CHMUnitFiltable(unit: CHMUnit(path: "/", children: [
8484
.init(path: "/a/", children: [
8585
.init(path: "/a/b"),
8686
.init(path: "/a/c")
8787
]),
8888
.init(path: "/d")
89-
]))]
89+
]))
9090
)
9191
}
9292
}

yCHM/IndexParser.swift

+3-3
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,14 @@
88
import Foundation
99
import SwiftSoup
1010

11-
func parseIndex(_ data: Data) -> [CHMUnit] {
11+
func parseIndex(_ data: Data) -> CHMUnit {
1212
let htmlStr = decodeString(data: data)
1313
do {
1414
let doc = try SwiftSoup.parse(htmlStr)
15-
return parseBody(doc.body()!).children ?? []
15+
return parseBody(doc.body()!)
1616
} catch {
1717
logger.error("parse error")
18-
return []
18+
return CHMUnit()
1919
}
2020
}
2121

yCHM/UnitViews.swift

+38-20
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,49 @@
88
import Foundation
99
import SwiftUI
1010

11-
class CHMUnitFiltable: CHMUnit, Hashable {
12-
let allChildren: [CHMUnitFiltable]?
13-
var filteredChildren: [CHMUnitFiltable]?
11+
class CHMUnitFiltable: CHMUnit, Hashable, ObservableObject {
12+
var allChildren: [CHMUnitFiltable]? = []
13+
@Published var filteredChildren: [CHMUnitFiltable]? = []
14+
var lastfilter: String = ""
15+
16+
override init() {
17+
super.init()
18+
}
1419

1520
init(unit: CHMUnit) {
1621
allChildren = unit.children?.map({ CHMUnitFiltable(unit: $0) })
1722
filteredChildren = allChildren
1823
super.init(unit)
1924
}
2025

26+
func load(unit: CHMUnit) {
27+
name = unit.name
28+
path = unit.path
29+
parent = unit.parent
30+
children = unit.children
31+
allChildren = unit.children?.map({ CHMUnitFiltable(unit: $0) })
32+
filteredChildren = allChildren
33+
}
34+
35+
func filter(text: String) -> CHMUnitFiltable {
36+
if lastfilter == text {
37+
// urgely but break the update loop
38+
return self
39+
}
40+
self.filteredChildren = allChildren?.filter({
41+
if fuzzyMatch(query: text, text: $0.name) {
42+
return true
43+
}
44+
var _ = $0.filter(text: text)
45+
if ($0.filteredChildren?.count ?? -1) > 0 {
46+
return true
47+
}
48+
return false
49+
})
50+
lastfilter = text
51+
return self
52+
}
53+
2154
static func == (lhs: CHMUnitFiltable, rhs: CHMUnitFiltable) -> Bool {
2255
return lhs.id == rhs.id
2356
}
@@ -28,13 +61,13 @@ class CHMUnitFiltable: CHMUnit, Hashable {
2861
}
2962

3063
struct TreeView: View {
31-
@Binding var items: [CHMUnitFiltable]
64+
@ObservedObject var items: CHMUnitFiltable
3265
@Binding var textFilter: String
3366
@Binding var selected: CHMUnitFiltable?
3467

3568
var body: some View {
3669
List(
37-
filterByText(query: textFilter, items: items),
70+
items.filter(text: textFilter).filteredChildren!,
3871
id: \.self, children: \.filteredChildren,
3972
selection: $selected) { unit in
4073
UnitView(unit: unit)
@@ -51,21 +84,6 @@ struct UnitView: View {
5184

5285
}
5386

54-
func filterByText(query: String, items: [CHMUnitFiltable]) -> [CHMUnitFiltable]
55-
{
56-
return items.compactMap({
57-
if fuzzyMatch(query: query, text: $0.name) {
58-
return $0
59-
}
60-
let filteredChildren = filterByText(query: query, items: $0.allChildren ?? [])
61-
if filteredChildren.count > 0 {
62-
$0.filteredChildren = filteredChildren
63-
return $0
64-
}
65-
return nil
66-
})
67-
}
68-
6987
func fuzzyMatch(query: String, text: String) -> Bool {
7088
var idx: String.Index? = text.startIndex
7189
for i in query {

yCHMTests/IndexParserTests.swift

+3-2
Original file line numberDiff line numberDiff line change
@@ -158,14 +158,15 @@ class IndexParserTests: XCTestCase {
158158

159159
func testPerformance() throws {
160160
let data = testHtml1.data(using: .utf8)!
161-
var res: [CHMUnit] = []
161+
var res: CHMUnit = CHMUnit()
162162
self.measure {
163163
res = parseIndex(data)
164164
}
165165
assertIndexIsRight(res)
166166
}
167167

168-
func assertIndexIsRight(_ units: [CHMUnit], specialItem: String = "specialitem") {
168+
func assertIndexIsRight(_ unit: CHMUnit, specialItem: String = "specialitem") {
169+
let units = unit.children!
169170
XCTAssertEqual(units.count, 3)
170171
XCTAssertEqual(units[0].name, "a")
171172
XCTAssertEqual(units[1].name, "b")

0 commit comments

Comments
 (0)