Skip to content

Commit e6685e9

Browse files
committed
Migrate HostApp and dependencies to new version of TCA
1 parent 9bb08cc commit e6685e9

29 files changed

+555
-613
lines changed

Core/Package.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,10 +93,10 @@ let package = Package(
9393
.package(url: "https://github.com/gonzalezreal/swift-markdown-ui", from: "2.1.0"),
9494
.package(url: "https://github.com/sparkle-project/Sparkle", from: "2.0.0"),
9595
.package(url: "https://github.com/pointfreeco/swift-parsing", from: "0.12.1"),
96-
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "0.5.1"),
96+
.package(url: "https://github.com/pointfreeco/swift-dependencies", from: "1.0.0"),
9797
.package(
9898
url: "https://github.com/pointfreeco/swift-composable-architecture",
99-
from: "0.55.0"
99+
from: "1.10.4"
100100
),
101101
// quick hack to support custom UserDefaults
102102
// https://github.com/sindresorhus/KeyboardShortcuts

Core/Sources/HostApp/AccountSettings/APIKeyManagement/APIKeyManagementView.swift

Lines changed: 74 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -3,104 +3,104 @@ import SharedUIComponents
33
import SwiftUI
44

55
struct APIKeyManagementView: View {
6-
let store: StoreOf<APIKeyManagement>
6+
@Perception.Bindable var store: StoreOf<APIKeyManagement>
77

88
var body: some View {
9-
VStack(spacing: 0) {
10-
HStack {
11-
Button(action: {
12-
store.send(.closeButtonClicked)
13-
}) {
14-
Image(systemName: "xmark.circle.fill")
15-
.foregroundStyle(.secondary)
16-
.padding()
17-
}
18-
.buttonStyle(.plain)
19-
Text("API Keys")
20-
Spacer()
21-
Button(action: {
22-
store.send(.addButtonClicked)
23-
}) {
24-
Image(systemName: "plus.circle.fill")
25-
.foregroundStyle(.secondary)
26-
.padding()
9+
WithPerceptionTracking {
10+
VStack(spacing: 0) {
11+
HStack {
12+
Button(action: {
13+
store.send(.closeButtonClicked)
14+
}) {
15+
Image(systemName: "xmark.circle.fill")
16+
.foregroundStyle(.secondary)
17+
.padding()
18+
}
19+
.buttonStyle(.plain)
20+
Text("API Keys")
21+
Spacer()
22+
Button(action: {
23+
store.send(.addButtonClicked)
24+
}) {
25+
Image(systemName: "plus.circle.fill")
26+
.foregroundStyle(.secondary)
27+
.padding()
28+
}
29+
.buttonStyle(.plain)
2730
}
28-
.buttonStyle(.plain)
29-
}
30-
.background(Color(nsColor: .separatorColor))
31-
32-
List {
33-
WithViewStore(store, observe: { $0.availableAPIKeyNames }) { viewStore in
34-
ForEach(viewStore.state, id: \.self) { name in
35-
HStack {
36-
Text(name)
37-
.contextMenu {
38-
Button("Remove") {
39-
viewStore.send(.deleteButtonClicked(name: name))
31+
.background(Color(nsColor: .separatorColor))
32+
33+
List {
34+
WithPerceptionTracking {
35+
ForEach(store.availableAPIKeyNames, id: \.self) { name in
36+
HStack {
37+
Text(name)
38+
.contextMenu {
39+
Button("Remove") {
40+
store.send(.deleteButtonClicked(name: name))
41+
}
4042
}
43+
Spacer()
44+
45+
Button(action: {
46+
store.send(.deleteButtonClicked(name: name))
47+
}) {
48+
Image(systemName: "trash.fill")
49+
.foregroundStyle(.secondary)
4150
}
42-
Spacer()
43-
44-
Button(action: {
45-
viewStore.send(.deleteButtonClicked(name: name))
46-
}) {
47-
Image(systemName: "trash.fill")
48-
.foregroundStyle(.secondary)
51+
.buttonStyle(.plain)
4952
}
50-
.buttonStyle(.plain)
5153
}
52-
}
53-
.modify { view in
54-
if #available(macOS 13.0, *) {
55-
view.listRowSeparator(.hidden).listSectionSeparator(.hidden)
56-
} else {
57-
view
54+
.modify { view in
55+
if #available(macOS 13.0, *) {
56+
view.listRowSeparator(.hidden).listSectionSeparator(.hidden)
57+
} else {
58+
view
59+
}
5860
}
5961
}
6062
}
61-
}
62-
.removeBackground()
63-
.overlay {
64-
WithViewStore(store, observe: { $0.availableAPIKeyNames }) { viewStore in
65-
if viewStore.state.isEmpty {
66-
Text("""
63+
.removeBackground()
64+
.overlay {
65+
WithPerceptionTracking {
66+
if store.availableAPIKeyNames.isEmpty {
67+
Text("""
6768
Empty
6869
Add a new key by clicking the add button
6970
""")
70-
.multilineTextAlignment(.center)
71-
.padding()
71+
.multilineTextAlignment(.center)
72+
.padding()
73+
}
7274
}
7375
}
7476
}
75-
}
76-
.focusable(false)
77-
.frame(width: 300, height: 400)
78-
.background(.thickMaterial)
79-
.onAppear {
80-
store.send(.appear)
81-
}
82-
.sheet(store: store.scope(
83-
state: \.$apiKeySubmission,
84-
action: APIKeyManagement.Action.apiKeySubmission
85-
)) { store in
86-
APIKeySubmissionView(store: store)
87-
.frame(minWidth: 400)
77+
.focusable(false)
78+
.frame(width: 300, height: 400)
79+
.background(.thickMaterial)
80+
.onAppear {
81+
store.send(.appear)
82+
}
83+
.sheet(item: $store.scope(
84+
state: \.apiKeySubmission,
85+
action: \.apiKeySubmission
86+
)) { store in
87+
APIKeySubmissionView(store: store)
88+
.frame(minWidth: 400)
89+
}
8890
}
8991
}
9092
}
9193

9294
struct APIKeySubmissionView: View {
93-
let store: StoreOf<APIKeySubmission>
95+
@Perception.Bindable var store: StoreOf<APIKeySubmission>
9496

9597
var body: some View {
9698
ScrollView {
9799
VStack(spacing: 0) {
98100
Form {
99-
WithViewStore(store, removeDuplicates: { $0.name == $1.name }) { viewStore in
100-
TextField("Name", text: viewStore.$name)
101-
}
102-
WithViewStore(store, removeDuplicates: { $0.key == $1.key }) { viewStore in
103-
SecureField("Key", text: viewStore.$key)
101+
WithPerceptionTracking {
102+
TextField("Name", text: $store.name)
103+
SecureField("Key", text: $store.key)
104104
}
105105
}.padding()
106106

@@ -128,7 +128,7 @@ class APIKeyManagementView_Preview: PreviewProvider {
128128
initialState: .init(
129129
availableAPIKeyNames: ["test1", "test2"]
130130
),
131-
reducer: APIKeyManagement()
131+
reducer: { APIKeyManagement() }
132132
)
133133
)
134134
}
@@ -139,7 +139,7 @@ class APIKeySubmissionView_Preview: PreviewProvider {
139139
APIKeySubmissionView(
140140
store: .init(
141141
initialState: .init(),
142-
reducer: APIKeySubmission()
142+
reducer: { APIKeySubmission() }
143143
)
144144
)
145145
}

Core/Sources/HostApp/AccountSettings/APIKeyManagement/APIKeyManangement.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import ComposableArchitecture
22
import Foundation
33

4-
struct APIKeyManagement: ReducerProtocol {
4+
@Reducer
5+
struct APIKeyManagement {
6+
@ObservableState
57
struct State: Equatable {
68
var availableAPIKeyNames: [String] = []
7-
@PresentationState var apiKeySubmission: APIKeySubmission.State?
9+
@Presents var apiKeySubmission: APIKeySubmission.State?
810
}
911

1012
enum Action: Equatable {
@@ -20,7 +22,7 @@ struct APIKeyManagement: ReducerProtocol {
2022
@Dependency(\.toast) var toast
2123
@Dependency(\.apiKeyKeychain) var keychain
2224

23-
var body: some ReducerProtocol<State, Action> {
25+
var body: some ReducerOf<Self> {
2426
Reduce { state, action in
2527
switch action {
2628
case .appear:
@@ -72,7 +74,7 @@ struct APIKeyManagement: ReducerProtocol {
7274
return .none
7375
}
7476
}
75-
.ifLet(\.$apiKeySubmission, action: /Action.apiKeySubmission) {
77+
.ifLet(\.$apiKeySubmission, action: \.apiKeySubmission) {
7678
APIKeySubmission()
7779
}
7880
}

Core/Sources/HostApp/AccountSettings/APIKeyManagement/APIKeyPicker.swift

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,26 +2,26 @@ import ComposableArchitecture
22
import SwiftUI
33

44
struct APIKeyPicker: View {
5-
let store: StoreOf<APIKeySelection>
5+
@Perception.Bindable var store: StoreOf<APIKeySelection>
66

77
var body: some View {
8-
WithViewStore(store) { viewStore in
8+
WithPerceptionTracking {
99
HStack {
1010
Picker(
11-
selection: viewStore.$apiKeyName,
11+
selection: $store.apiKeyName,
1212
content: {
1313
Text("No API Key").tag("")
14-
if viewStore.state.availableAPIKeyNames.isEmpty {
14+
if store.availableAPIKeyNames.isEmpty {
1515
Text("No API key found, please add a new one →")
1616
}
1717

18-
if !viewStore.state.availableAPIKeyNames.contains(viewStore.state.apiKeyName),
19-
!viewStore.state.apiKeyName.isEmpty {
20-
Text("Key not found: \(viewStore.state.apiKeyName)")
21-
.tag(viewStore.state.apiKeyName)
18+
if !store.availableAPIKeyNames.contains(store.apiKeyName),
19+
!store.apiKeyName.isEmpty {
20+
Text("Key not found: \(store.apiKeyName)")
21+
.tag(store.apiKeyName)
2222
}
2323

24-
ForEach(viewStore.state.availableAPIKeyNames, id: \.self) { name in
24+
ForEach(store.availableAPIKeyNames, id: \.self) { name in
2525
Text(name).tag(name)
2626
}
2727

@@ -32,10 +32,10 @@ struct APIKeyPicker: View {
3232
Button(action: { store.send(.manageAPIKeysButtonClicked) }) {
3333
Text(Image(systemName: "key"))
3434
}
35-
}.sheet(isPresented: viewStore.$isAPIKeyManagementPresented) {
35+
}.sheet(isPresented: $store.isAPIKeyManagementPresented) {
3636
APIKeyManagementView(store: store.scope(
3737
state: \.apiKeyManagement,
38-
action: APIKeySelection.Action.apiKeyManagement
38+
action: \.apiKeyManagement
3939
))
4040
}
4141
}

Core/Sources/HostApp/AccountSettings/APIKeyManagement/APIKeySelection.swift

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,14 +2,16 @@ import Foundation
22
import SwiftUI
33
import ComposableArchitecture
44

5-
struct APIKeySelection: ReducerProtocol {
5+
@Reducer
6+
struct APIKeySelection {
7+
@ObservableState
68
struct State: Equatable {
7-
@BindingState var apiKeyName: String = ""
9+
var apiKeyName: String = ""
810
var availableAPIKeyNames: [String] {
911
apiKeyManagement.availableAPIKeyNames
1012
}
1113
var apiKeyManagement: APIKeyManagement.State = .init()
12-
@BindingState var isAPIKeyManagementPresented: Bool = false
14+
var isAPIKeyManagementPresented: Bool = false
1315
}
1416

1517
enum Action: Equatable, BindableAction {
@@ -23,10 +25,10 @@ struct APIKeySelection: ReducerProtocol {
2325
@Dependency(\.toast) var toast
2426
@Dependency(\.apiKeyKeychain) var keychain
2527

26-
var body: some ReducerProtocol<State, Action> {
28+
var body: some ReducerOf<Self> {
2729
BindingReducer()
2830

29-
Scope(state: \.apiKeyManagement, action: /Action.apiKeyManagement) {
31+
Scope(state: \.apiKeyManagement, action: \.apiKeyManagement) {
3032
APIKeyManagement()
3133
}
3234

Core/Sources/HostApp/AccountSettings/APIKeyManagement/APIKeySubmission.swift

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
11
import ComposableArchitecture
22
import Foundation
33

4-
struct APIKeySubmission: ReducerProtocol {
4+
@Reducer
5+
struct APIKeySubmission {
6+
@ObservableState
57
struct State: Equatable {
6-
@BindingState var name: String = ""
7-
@BindingState var key: String = ""
8+
var name: String = ""
9+
var key: String = ""
810
}
911

1012
enum Action: Equatable, BindableAction {
@@ -22,7 +24,7 @@ struct APIKeySubmission: ReducerProtocol {
2224
case keyIsEmpty
2325
}
2426

25-
var body: some ReducerProtocol<State, Action> {
27+
var body: some ReducerOf<Self> {
2628
BindingReducer()
2729

2830
Reduce { state, action in

0 commit comments

Comments
 (0)