Skip to content

Commit 221848a

Browse files
committed
Add macOS Menu bar app
1 parent 833d28d commit 221848a

File tree

20 files changed

+394
-13
lines changed

20 files changed

+394
-13
lines changed
Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,8 @@ class ChatGPTAPI {
128128
throw error
129129
}
130130
}
131-
132131
}
133132

134-
135133
extension String: CustomNSError {
136134

137135
public var errorUserInfo: [String : Any] {
Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,9 @@
88
import SwiftUI
99

1010
struct ContentView: View {
11-
11+
1212
@Environment(\.colorScheme) var colorScheme
13-
@StateObject var vm = ViewModel(api: ChatGPTAPI(apiKey: "PROVIDE_YOUR_API_KEY"))
13+
@ObservedObject var vm: ViewModel
1414
@FocusState var isTextFieldFocused: Bool
1515

1616
var body: some View {
@@ -82,6 +82,11 @@ struct ContentView: View {
8282
.rotationEffect(.degrees(45))
8383
.font(.system(size: 30))
8484
}
85+
#if os(macOS)
86+
.buttonStyle(.borderless)
87+
.keyboardShortcut(.defaultAction)
88+
.foregroundColor(.accentColor)
89+
#endif
8590
.disabled(vm.inputMessage.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty)
8691

8792
}
@@ -99,7 +104,7 @@ struct ContentView: View {
99104
struct ContentView_Previews: PreviewProvider {
100105
static var previews: some View {
101106
NavigationStack {
102-
ContentView()
107+
ContentView(vm: ViewModel(api: ChatGPTAPI(apiKey: "PROVIDE_API_KEY")))
103108
}
104109
}
105110
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,13 @@ class ViewModel: ObservableObject {
2727
await send(text: text)
2828
}
2929

30+
@MainActor
31+
func clearMessages() {
32+
withAnimation { [weak self] in
33+
self?.messages = []
34+
}
35+
}
36+
3037
@MainActor
3138
func retry(message: MessageRow) async {
3239
guard let index = messages.firstIndex(where: { $0.id == message.id }) else {

XCAChatGPT.xcodeproj/project.pbxproj

Lines changed: 167 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@
77
objects = {
88

99
/* Begin PBXBuildFile section */
10+
8B057585298E52C000A56C9A /* XCAChatGPTMacApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B057584298E52C000A56C9A /* XCAChatGPTMacApp.swift */; };
11+
8B057589298E52C000A56C9A /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B057588298E52C000A56C9A /* Assets.xcassets */; };
12+
8B05758C298E52C000A56C9A /* Preview Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B05758B298E52C000A56C9A /* Preview Assets.xcassets */; };
13+
8B057592298E52D900A56C9A /* DotLoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C017298ADF4E0079AF26 /* DotLoadingView.swift */; };
14+
8B057593298E52D900A56C9A /* ChatGPTAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C011298AD0CE0079AF26 /* ChatGPTAPI.swift */; };
15+
8B057594298E52D900A56C9A /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C005298AD09E0079AF26 /* ContentView.swift */; };
16+
8B057595298E52D900A56C9A /* MessageRowView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C019298ADF7F0079AF26 /* MessageRowView.swift */; };
17+
8B057596298E52DD00A56C9A /* ViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C013298ADC560079AF26 /* ViewModel.swift */; };
18+
8B057597298E52DD00A56C9A /* MessageRow.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C015298ADC9D0079AF26 /* MessageRow.swift */; };
1019
8B91C004298AD09E0079AF26 /* XCAChatGPTApp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C003298AD09E0079AF26 /* XCAChatGPTApp.swift */; };
1120
8B91C006298AD09E0079AF26 /* ContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B91C005298AD09E0079AF26 /* ContentView.swift */; };
1221
8B91C008298AD09F0079AF26 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8B91C007298AD09F0079AF26 /* Assets.xcassets */; };
@@ -19,6 +28,11 @@
1928
/* End PBXBuildFile section */
2029

2130
/* Begin PBXFileReference section */
31+
8B057582298E52C000A56C9A /* XCAChatGPTMac.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XCAChatGPTMac.app; sourceTree = BUILT_PRODUCTS_DIR; };
32+
8B057584298E52C000A56C9A /* XCAChatGPTMacApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCAChatGPTMacApp.swift; sourceTree = "<group>"; };
33+
8B057588298E52C000A56C9A /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
34+
8B05758B298E52C000A56C9A /* Preview Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = "Preview Assets.xcassets"; sourceTree = "<group>"; };
35+
8B05758D298E52C000A56C9A /* XCAChatGPTMac.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = XCAChatGPTMac.entitlements; sourceTree = "<group>"; };
2236
8B91C000298AD09E0079AF26 /* XCAChatGPT.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = XCAChatGPT.app; sourceTree = BUILT_PRODUCTS_DIR; };
2337
8B91C003298AD09E0079AF26 /* XCAChatGPTApp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = XCAChatGPTApp.swift; sourceTree = "<group>"; };
2438
8B91C005298AD09E0079AF26 /* ContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContentView.swift; sourceTree = "<group>"; };
@@ -32,6 +46,13 @@
3246
/* End PBXFileReference section */
3347

3448
/* Begin PBXFrameworksBuildPhase section */
49+
8B05757F298E52C000A56C9A /* Frameworks */ = {
50+
isa = PBXFrameworksBuildPhase;
51+
buildActionMask = 2147483647;
52+
files = (
53+
);
54+
runOnlyForDeploymentPostprocessing = 0;
55+
};
3556
8B91BFFD298AD09E0079AF26 /* Frameworks */ = {
3657
isa = PBXFrameworksBuildPhase;
3758
buildActionMask = 2147483647;
@@ -42,10 +63,44 @@
4263
/* End PBXFrameworksBuildPhase section */
4364

4465
/* Begin PBXGroup section */
66+
8B057583298E52C000A56C9A /* XCAChatGPTMac */ = {
67+
isa = PBXGroup;
68+
children = (
69+
8B057584298E52C000A56C9A /* XCAChatGPTMacApp.swift */,
70+
8B057588298E52C000A56C9A /* Assets.xcassets */,
71+
8B05758D298E52C000A56C9A /* XCAChatGPTMac.entitlements */,
72+
8B05758A298E52C000A56C9A /* Preview Content */,
73+
);
74+
path = XCAChatGPTMac;
75+
sourceTree = "<group>";
76+
};
77+
8B05758A298E52C000A56C9A /* Preview Content */ = {
78+
isa = PBXGroup;
79+
children = (
80+
8B05758B298E52C000A56C9A /* Preview Assets.xcassets */,
81+
);
82+
path = "Preview Content";
83+
sourceTree = "<group>";
84+
};
85+
8B057591298E52CB00A56C9A /* Shared */ = {
86+
isa = PBXGroup;
87+
children = (
88+
8B91C011298AD0CE0079AF26 /* ChatGPTAPI.swift */,
89+
8B91C005298AD09E0079AF26 /* ContentView.swift */,
90+
8B91C017298ADF4E0079AF26 /* DotLoadingView.swift */,
91+
8B91C019298ADF7F0079AF26 /* MessageRowView.swift */,
92+
8B91C013298ADC560079AF26 /* ViewModel.swift */,
93+
8B91C015298ADC9D0079AF26 /* MessageRow.swift */,
94+
);
95+
path = Shared;
96+
sourceTree = "<group>";
97+
};
4598
8B91BFF7298AD09E0079AF26 = {
4699
isa = PBXGroup;
47100
children = (
101+
8B057591298E52CB00A56C9A /* Shared */,
48102
8B91C002298AD09E0079AF26 /* XCAChatGPT */,
103+
8B057583298E52C000A56C9A /* XCAChatGPTMac */,
49104
8B91C001298AD09E0079AF26 /* Products */,
50105
);
51106
sourceTree = "<group>";
@@ -54,6 +109,7 @@
54109
isa = PBXGroup;
55110
children = (
56111
8B91C000298AD09E0079AF26 /* XCAChatGPT.app */,
112+
8B057582298E52C000A56C9A /* XCAChatGPTMac.app */,
57113
);
58114
name = Products;
59115
sourceTree = "<group>";
@@ -62,14 +118,8 @@
62118
isa = PBXGroup;
63119
children = (
64120
8B91C003298AD09E0079AF26 /* XCAChatGPTApp.swift */,
65-
8B91C011298AD0CE0079AF26 /* ChatGPTAPI.swift */,
66-
8B91C005298AD09E0079AF26 /* ContentView.swift */,
67-
8B91C017298ADF4E0079AF26 /* DotLoadingView.swift */,
68-
8B91C019298ADF7F0079AF26 /* MessageRowView.swift */,
69121
8B91C007298AD09F0079AF26 /* Assets.xcassets */,
70122
8B91C009298AD09F0079AF26 /* Preview Content */,
71-
8B91C013298ADC560079AF26 /* ViewModel.swift */,
72-
8B91C015298ADC9D0079AF26 /* MessageRow.swift */,
73123
);
74124
path = XCAChatGPT;
75125
sourceTree = "<group>";
@@ -85,6 +135,23 @@
85135
/* End PBXGroup section */
86136

87137
/* Begin PBXNativeTarget section */
138+
8B057581298E52C000A56C9A /* XCAChatGPTMac */ = {
139+
isa = PBXNativeTarget;
140+
buildConfigurationList = 8B057590298E52C000A56C9A /* Build configuration list for PBXNativeTarget "XCAChatGPTMac" */;
141+
buildPhases = (
142+
8B05757E298E52C000A56C9A /* Sources */,
143+
8B05757F298E52C000A56C9A /* Frameworks */,
144+
8B057580298E52C000A56C9A /* Resources */,
145+
);
146+
buildRules = (
147+
);
148+
dependencies = (
149+
);
150+
name = XCAChatGPTMac;
151+
productName = XCAChatGPTMac;
152+
productReference = 8B057582298E52C000A56C9A /* XCAChatGPTMac.app */;
153+
productType = "com.apple.product-type.application";
154+
};
88155
8B91BFFF298AD09E0079AF26 /* XCAChatGPT */ = {
89156
isa = PBXNativeTarget;
90157
buildConfigurationList = 8B91C00E298AD09F0079AF26 /* Build configuration list for PBXNativeTarget "XCAChatGPT" */;
@@ -112,6 +179,9 @@
112179
LastSwiftUpdateCheck = 1420;
113180
LastUpgradeCheck = 1420;
114181
TargetAttributes = {
182+
8B057581298E52C000A56C9A = {
183+
CreatedOnToolsVersion = 14.2;
184+
};
115185
8B91BFFF298AD09E0079AF26 = {
116186
CreatedOnToolsVersion = 14.2;
117187
};
@@ -131,11 +201,21 @@
131201
projectRoot = "";
132202
targets = (
133203
8B91BFFF298AD09E0079AF26 /* XCAChatGPT */,
204+
8B057581298E52C000A56C9A /* XCAChatGPTMac */,
134205
);
135206
};
136207
/* End PBXProject section */
137208

138209
/* Begin PBXResourcesBuildPhase section */
210+
8B057580298E52C000A56C9A /* Resources */ = {
211+
isa = PBXResourcesBuildPhase;
212+
buildActionMask = 2147483647;
213+
files = (
214+
8B05758C298E52C000A56C9A /* Preview Assets.xcassets in Resources */,
215+
8B057589298E52C000A56C9A /* Assets.xcassets in Resources */,
216+
);
217+
runOnlyForDeploymentPostprocessing = 0;
218+
};
139219
8B91BFFE298AD09E0079AF26 /* Resources */ = {
140220
isa = PBXResourcesBuildPhase;
141221
buildActionMask = 2147483647;
@@ -148,6 +228,20 @@
148228
/* End PBXResourcesBuildPhase section */
149229

150230
/* Begin PBXSourcesBuildPhase section */
231+
8B05757E298E52C000A56C9A /* Sources */ = {
232+
isa = PBXSourcesBuildPhase;
233+
buildActionMask = 2147483647;
234+
files = (
235+
8B057597298E52DD00A56C9A /* MessageRow.swift in Sources */,
236+
8B057593298E52D900A56C9A /* ChatGPTAPI.swift in Sources */,
237+
8B057594298E52D900A56C9A /* ContentView.swift in Sources */,
238+
8B057592298E52D900A56C9A /* DotLoadingView.swift in Sources */,
239+
8B057595298E52D900A56C9A /* MessageRowView.swift in Sources */,
240+
8B057585298E52C000A56C9A /* XCAChatGPTMacApp.swift in Sources */,
241+
8B057596298E52DD00A56C9A /* ViewModel.swift in Sources */,
242+
);
243+
runOnlyForDeploymentPostprocessing = 0;
244+
};
151245
8B91BFFC298AD09E0079AF26 /* Sources */ = {
152246
isa = PBXSourcesBuildPhase;
153247
buildActionMask = 2147483647;
@@ -165,6 +259,64 @@
165259
/* End PBXSourcesBuildPhase section */
166260

167261
/* Begin XCBuildConfiguration section */
262+
8B05758E298E52C000A56C9A /* Debug */ = {
263+
isa = XCBuildConfiguration;
264+
buildSettings = {
265+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
266+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
267+
CODE_SIGN_ENTITLEMENTS = XCAChatGPTMac/XCAChatGPTMac.entitlements;
268+
CODE_SIGN_STYLE = Automatic;
269+
COMBINE_HIDPI_IMAGES = YES;
270+
CURRENT_PROJECT_VERSION = 1;
271+
DEVELOPMENT_ASSET_PATHS = "\"XCAChatGPTMac/Preview Content\"";
272+
DEVELOPMENT_TEAM = 5C2XD9H2JS;
273+
ENABLE_HARDENED_RUNTIME = YES;
274+
ENABLE_PREVIEWS = YES;
275+
GENERATE_INFOPLIST_FILE = YES;
276+
INFOPLIST_KEY_NSHumanReadableCopyright = "";
277+
LD_RUNPATH_SEARCH_PATHS = (
278+
"$(inherited)",
279+
"@executable_path/../Frameworks",
280+
);
281+
MACOSX_DEPLOYMENT_TARGET = 13.1;
282+
MARKETING_VERSION = 1.0;
283+
PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.XCAChatGPTMac;
284+
PRODUCT_NAME = "$(TARGET_NAME)";
285+
SDKROOT = macosx;
286+
SWIFT_EMIT_LOC_STRINGS = YES;
287+
SWIFT_VERSION = 5.0;
288+
};
289+
name = Debug;
290+
};
291+
8B05758F298E52C000A56C9A /* Release */ = {
292+
isa = XCBuildConfiguration;
293+
buildSettings = {
294+
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
295+
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
296+
CODE_SIGN_ENTITLEMENTS = XCAChatGPTMac/XCAChatGPTMac.entitlements;
297+
CODE_SIGN_STYLE = Automatic;
298+
COMBINE_HIDPI_IMAGES = YES;
299+
CURRENT_PROJECT_VERSION = 1;
300+
DEVELOPMENT_ASSET_PATHS = "\"XCAChatGPTMac/Preview Content\"";
301+
DEVELOPMENT_TEAM = 5C2XD9H2JS;
302+
ENABLE_HARDENED_RUNTIME = YES;
303+
ENABLE_PREVIEWS = YES;
304+
GENERATE_INFOPLIST_FILE = YES;
305+
INFOPLIST_KEY_NSHumanReadableCopyright = "";
306+
LD_RUNPATH_SEARCH_PATHS = (
307+
"$(inherited)",
308+
"@executable_path/../Frameworks",
309+
);
310+
MACOSX_DEPLOYMENT_TARGET = 13.1;
311+
MARKETING_VERSION = 1.0;
312+
PRODUCT_BUNDLE_IDENTIFIER = com.alfianlosari.XCAChatGPTMac;
313+
PRODUCT_NAME = "$(TARGET_NAME)";
314+
SDKROOT = macosx;
315+
SWIFT_EMIT_LOC_STRINGS = YES;
316+
SWIFT_VERSION = 5.0;
317+
};
318+
name = Release;
319+
};
168320
8B91C00C298AD09F0079AF26 /* Debug */ = {
169321
isa = XCBuildConfiguration;
170322
buildSettings = {
@@ -340,6 +492,15 @@
340492
/* End XCBuildConfiguration section */
341493

342494
/* Begin XCConfigurationList section */
495+
8B057590298E52C000A56C9A /* Build configuration list for PBXNativeTarget "XCAChatGPTMac" */ = {
496+
isa = XCConfigurationList;
497+
buildConfigurations = (
498+
8B05758E298E52C000A56C9A /* Debug */,
499+
8B05758F298E52C000A56C9A /* Release */,
500+
);
501+
defaultConfigurationIsVisible = 0;
502+
defaultConfigurationName = Release;
503+
};
343504
8B91BFFB298AD09E0079AF26 /* Build configuration list for PBXProject "XCAChatGPT" */ = {
344505
isa = XCConfigurationList;
345506
buildConfigurations = (

XCAChatGPT/XCAChatGPTApp.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@ import SwiftUI
99

1010
@main
1111
struct XCAChatGPTApp: App {
12+
13+
@StateObject var vm = ViewModel(api: ChatGPTAPI(apiKey: "PROVIDE_API_KEY"))
14+
1215
var body: some Scene {
1316
WindowGroup {
1417
NavigationStack {
15-
ContentView()
18+
ContentView(vm: vm)
1619
}
17-
1820
}
1921
}
2022
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}

0 commit comments

Comments
 (0)