@@ -16,10 +16,69 @@ struct CopilotView: View {
1616
1717 init ( ) { }
1818 }
19+
20+ class ViewModel : ObservableObject {
21+ let installationManager = GitHubCopilotInstallationManager ( )
22+
23+ @Published var installationStatus : GitHubCopilotInstallationManager . InstallationStatus
24+ @Published var installationStep : GitHubCopilotInstallationManager . InstallationStep ?
25+
26+ init ( ) {
27+ installationStatus = installationManager. checkInstallation ( )
28+ }
29+
30+ init (
31+ installationStatus: GitHubCopilotInstallationManager . InstallationStatus ,
32+ installationStep: GitHubCopilotInstallationManager . InstallationStep ?
33+ ) {
34+ assert ( isPreview)
35+ self . installationStatus = installationStatus
36+ self . installationStep = installationStep
37+ }
38+
39+ func refreshInstallationStatus( ) {
40+ Task { @MainActor in
41+ installationStatus = installationManager. checkInstallation ( )
42+ }
43+ }
44+
45+ func install( ) async throws {
46+ defer { refreshInstallationStatus ( ) }
47+ do {
48+ for try await step in installationManager. installLatestVersion ( ) {
49+ Task { @MainActor in
50+ self . installationStep = step
51+ }
52+ }
53+ Task {
54+ try await Task . sleep ( nanoseconds: 1_000_000_000 )
55+ Task { @MainActor in
56+ self . installationStep = nil
57+ }
58+ }
59+ } catch {
60+ Task { @MainActor in
61+ installationStep = nil
62+ }
63+ throw error
64+ }
65+ }
66+
67+ func uninstall( ) {
68+ Task {
69+ defer { refreshInstallationStatus ( ) }
70+ try await installationManager. uninstall ( )
71+ Task { @MainActor in
72+ CopilotView . copilotAuthService = nil
73+ }
74+ }
75+ }
76+ }
1977
2078 @Environment ( \. openURL) var openURL
2179 @Environment ( \. toast) var toast
2280 @StateObject var settings = Settings ( )
81+ @StateObject var viewModel = ViewModel ( )
2382
2483 @State var status : GitHubCopilotAccountStatus ?
2584 @State var userCode : String ?
@@ -33,6 +92,30 @@ struct CopilotView: View {
3392 Self . copilotAuthService = service
3493 return service
3594 }
95+
96+ var installButton : some View {
97+ Button ( action: {
98+ Task {
99+ do {
100+ try await viewModel. install ( )
101+ } catch {
102+ toast ( Text ( error. localizedDescription) , . error)
103+ }
104+ }
105+ } ) {
106+ Text ( " Install " )
107+ }
108+ . disabled ( viewModel. installationStep != nil )
109+ }
110+
111+ var uninstallButton : some View {
112+ Button ( action: {
113+ viewModel. uninstall ( )
114+ } ) {
115+ Text ( " Uninstall " )
116+ }
117+ . disabled ( viewModel. installationStep != nil )
118+ }
36119
37120 var body : some View {
38121 HStack {
@@ -66,7 +149,15 @@ struct CopilotView: View {
66149 . foregroundColor ( . secondary)
67150
68151 VStack ( alignment: . leading) {
69- Text ( " Language Server Version: \( version ?? " Loading.. " ) " )
152+ HStack {
153+ Text ( " Language Server Version: \( version ?? " Loading.. " ) " )
154+ switch viewModel. installationStatus {
155+ case . notInstalled:
156+ installButton
157+ case . installed:
158+ uninstallButton
159+ }
160+ }
70161 Text ( " Status: \( status? . description ?? " Loading.. " ) " )
71162
72163 HStack ( alignment: . center) {
0 commit comments