diff --git a/Copilot for Xcode/Assets.xcassets/WarningBackgroundColor.colorset/Contents.json b/Copilot for Xcode/Assets.xcassets/WarningBackgroundColor.colorset/Contents.json new file mode 100644 index 0000000..b38fae8 --- /dev/null +++ b/Copilot for Xcode/Assets.xcassets/WarningBackgroundColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xF5", + "green" : "0xF9", + "red" : "0xFF" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Copilot for Xcode/Assets.xcassets/WarningForegroundColor.colorset/Contents.json b/Copilot for Xcode/Assets.xcassets/WarningForegroundColor.colorset/Contents.json new file mode 100644 index 0000000..2d9762a --- /dev/null +++ b/Copilot for Xcode/Assets.xcassets/WarningForegroundColor.colorset/Contents.json @@ -0,0 +1,20 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0x07", + "green" : "0x37", + "red" : "0x8A" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + } +} diff --git a/Copilot for Xcode/Assets.xcassets/WarningStrokeColor.colorset/Contents.json b/Copilot for Xcode/Assets.xcassets/WarningStrokeColor.colorset/Contents.json new file mode 100644 index 0000000..a4651ba --- /dev/null +++ b/Copilot for Xcode/Assets.xcassets/WarningStrokeColor.colorset/Contents.json @@ -0,0 +1,23 @@ +{ + "colors" : [ + { + "color" : { + "color-space" : "srgb", + "components" : { + "alpha" : "1.000", + "blue" : "0xB4", + "green" : "0xCF", + "red" : "0xFD" + } + }, + "idiom" : "universal" + } + ], + "info" : { + "author" : "xcode", + "version" : 1 + }, + "properties" : { + "localizable" : true + } +} diff --git a/Core/Sources/HostApp/GeneralSettings/AppInfoView.swift b/Core/Sources/HostApp/GeneralSettings/AppInfoView.swift index e49c123..8fd3a5e 100644 --- a/Core/Sources/HostApp/GeneralSettings/AppInfoView.swift +++ b/Core/Sources/HostApp/GeneralSettings/AppInfoView.swift @@ -17,6 +17,7 @@ struct AppInfoView: View { @StateObject var viewModel: GitHubCopilotViewModel @State var appVersion = Bundle.main.infoDictionary?["CFBundleShortVersionString"] as? String + @State var automaticallyCheckForUpdates: Bool? let store: StoreOf @@ -47,8 +48,8 @@ struct AppInfoView: View { } HStack { Toggle(isOn: .init( - get: { updateChecker.getAutomaticallyChecksForUpdates() }, - set: { updateChecker.setAutomaticallyChecksForUpdates($0) } + get: { automaticallyCheckForUpdates ?? updateChecker.getAutomaticallyChecksForUpdates() }, + set: { updateChecker.setAutomaticallyChecksForUpdates($0); automaticallyCheckForUpdates = $0 } )) { Text("Automatically Check for Updates") } diff --git a/Core/Sources/HostApp/GeneralSettings/CopilotConnectionView.swift b/Core/Sources/HostApp/GeneralSettings/CopilotConnectionView.swift index 43a4aa8..0b62b86 100644 --- a/Core/Sources/HostApp/GeneralSettings/CopilotConnectionView.swift +++ b/Core/Sources/HostApp/GeneralSettings/CopilotConnectionView.swift @@ -21,7 +21,7 @@ struct CopilotConnectionView: View { var accountStatus: some View { SettingsButtonRow( title: "GitHub Account Status Permissions", - subtitle: "GitHub Connection: \(viewModel.status?.description ?? "Loading...")" + subtitle: "GitHub Account: \(viewModel.status?.description ?? "Loading...")" ) { if viewModel.isRunningAction || viewModel.waitingForSignIn { ProgressView().controlSize(.small) @@ -34,7 +34,7 @@ struct CopilotConnectionView: View { viewModel.cancelWaiting() } } else if viewModel.status == .notSignedIn { - Button("Login to GitHub") { + Button("Log in to GitHub") { viewModel.signIn() } .alert( @@ -56,7 +56,7 @@ struct CopilotConnectionView: View { if viewModel.status == .ok || viewModel.status == .alreadySignedIn || viewModel.status == .notAuthorized { - Button("Logout from GitHub") { viewModel.signOut() + Button("Log Out from GitHub") { viewModel.signOut() viewModel.isSignInAlertPresented = false } } @@ -64,9 +64,16 @@ struct CopilotConnectionView: View { } var connection: some View { - SettingsSection(title: "Copilot Connection") { + SettingsSection(title: "Account Settings", showWarning: viewModel.status == .notAuthorized) { accountStatus Divider() + if viewModel.status == .notAuthorized { + SettingsLink( + url: "https://github.com/features/copilot/plans", + title: "Enable powerful AI features for free with the GitHub Copilot Free plan" + ) + Divider() + } SettingsLink( url: "https://github.com/settings/copilot", title: "GitHub Copilot Account Settings" diff --git a/Core/Sources/HostApp/GitHubCopilotViewModel.swift b/Core/Sources/HostApp/GitHubCopilotViewModel.swift index 978fe2a..bbd01f2 100644 --- a/Core/Sources/HostApp/GitHubCopilotViewModel.swift +++ b/Core/Sources/HostApp/GitHubCopilotViewModel.swift @@ -61,13 +61,6 @@ class GitHubCopilotViewModel: ObservableObject { status = try await service.checkStatus() version = try await service.version() isRunningAction = false - - if status != .ok, status != .notSignedIn { - toast( - "GitHub Copilot status is not \"ok\". Please check if you have a valid GitHub Copilot subscription.", - .error - ) - } } catch { toast(error.localizedDescription, .error) } diff --git a/Core/Sources/HostApp/SharedComponents/SettingsSection.swift b/Core/Sources/HostApp/SharedComponents/SettingsSection.swift index fe679e2..e52d9ad 100644 --- a/Core/Sources/HostApp/SharedComponents/SettingsSection.swift +++ b/Core/Sources/HostApp/SharedComponents/SettingsSection.swift @@ -2,14 +2,36 @@ import SwiftUI struct SettingsSection: View { let title: String + let showWarning: Bool @ViewBuilder let content: () -> Content @ViewBuilder let footer: () -> Footer + + init(title: String, showWarning: Bool = false, @ViewBuilder content: @escaping () -> Content, @ViewBuilder footer: @escaping () -> Footer) { + self.title = title + self.showWarning = showWarning + self.content = content + self.footer = footer + } + var body: some View { VStack(alignment: .leading, spacing: 10) { Text(title) .bold() .padding(.horizontal, 10) + if showWarning { + HStack{ + Text("GitHub Copilot features are disabled. Please check your subscription to access them.") + .foregroundColor(Color("WarningForegroundColor")) + .padding(4) + Spacer() + } + .background(Color("WarningBackgroundColor")) + .overlay( + RoundedRectangle(cornerRadius: 3) + .stroke(Color("WarningStrokeColor"), lineWidth: 1) + ) + } VStack(alignment: .leading, spacing: 0) { content() } @@ -22,8 +44,8 @@ struct SettingsSection: View { } extension SettingsSection where Footer == EmptyView { - init(title: String, @ViewBuilder content: @escaping () -> Content) { - self.init(title: title, content: content, footer: { EmptyView() }) + init(title: String, showWarning: Bool = false, @ViewBuilder content: @escaping () -> Content) { + self.init(title: title, showWarning: showWarning, content: content, footer: { EmptyView() }) } } @@ -37,7 +59,7 @@ extension SettingsSection where Footer == EmptyView { Divider() SettingsLink(url: "https://example.com", title: "Example") } - SettingsSection(title: "Advanced") { + SettingsSection(title: "Advanced", showWarning: true) { SettingsLink(url: "https://example.com", title: "Example") } footer: { Text("Footer") diff --git a/Docs/macos-download-open-confirm.png b/Docs/macos-download-open-confirm.png new file mode 100644 index 0000000..de58a9a Binary files /dev/null and b/Docs/macos-download-open-confirm.png differ diff --git a/README.md b/README.md index 586350b..8eabfdb 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,13 @@ Use of the GitHub Copilot Xcode Extension is subject to [GitHub's Pre-Release Te Updates can be downloaded and installed by the app. -1. A background item will be added to enable Copilot to start when Xcode is opened. +1. Open the `GitHub Copilot for Xcode` application (from the `Applications` folder). Accept the security warning. +

+ Screenshot of MacOS download permission request +

+ + +1. A background item will be added to enable Copilot to start when `GitHub Copilot for Xcode` is opened.

Screenshot of background item

@@ -53,7 +59,7 @@ Use of the GitHub Copilot Xcode Extension is subject to [GitHub's Pre-Release Te

The `Xcode Source Editor Extension` permission needs to be enabled manually. Click - `Extension Permission` from the `Copilot for Xcode` settings to open the + `Extension Permission` from the `GitHub Copilot for Xcode` application settings to open the System Preferences to the `Extensions` panel. Select `Xcode Source Editor` and enable `GitHub Copilot`: @@ -61,8 +67,8 @@ Use of the GitHub Copilot Xcode Extension is subject to [GitHub's Pre-Release Te Screenshot of extension permission

-1. After granting the extension permission, please restart Xcode to ensure the - `Github Copilot` menu is available and not disabled under the Xcode `Editor` +1. After granting the extension permission, open Xcode. Verify that the + `Github Copilot` menu is available and enabled under the Xcode `Editor` menu.

diff --git a/Server/package-lock.json b/Server/package-lock.json index 88a089c..b3eefd7 100644 --- a/Server/package-lock.json +++ b/Server/package-lock.json @@ -8,16 +8,41 @@ "name": "@github/copilot-xcode", "version": "0.0.1", "dependencies": { - "@github/copilot-language-server": "^1.245.0" + "@github/copilot-language-server": "^1.263.0" } }, "node_modules/@github/copilot-language-server": { - "version": "1.245.0", - "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.245.0.tgz", - "integrity": "sha512-K/PSxLMQFhnM8CIhL0mF/FAEzB2EYqOEu0Ai0gvFEy+fMl3FvhxFkagb6w1qaQ0dQJSY5qExT88sABn3wDyHiA==", + "version": "1.263.0", + "resolved": "https://registry.npmjs.org/@github/copilot-language-server/-/copilot-language-server-1.263.0.tgz", + "integrity": "sha512-kf8M5kN1gYp+8yjk+yaH6iR9c8pSamWVpD7M6S2ZRkd3E4NqFGJe90Jgk6nub19tv5/qC7h7fHgeWxuhMRAGLQ==", + "dependencies": { + "vscode-languageserver-protocol": "^3.17.5" + }, "bin": { "copilot-language-server": "dist/language-server.js" } + }, + "node_modules/vscode-jsonrpc": { + "version": "8.2.0", + "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", + "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/vscode-languageserver-protocol": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", + "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", + "dependencies": { + "vscode-jsonrpc": "8.2.0", + "vscode-languageserver-types": "3.17.5" + } + }, + "node_modules/vscode-languageserver-types": { + "version": "3.17.5", + "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", + "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==" } } } diff --git a/Server/package.json b/Server/package.json index 68b97a1..b82186e 100644 --- a/Server/package.json +++ b/Server/package.json @@ -4,6 +4,6 @@ "description": "Package for downloading @github/copilot-language-server", "private": true, "dependencies": { - "@github/copilot-language-server": "^1.245.0" + "@github/copilot-language-server": "^1.263.0" } } diff --git a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotAccountStatus.swift b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotAccountStatus.swift index b4d28d1..2a10ed5 100644 --- a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotAccountStatus.swift +++ b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotAccountStatus.swift @@ -13,13 +13,13 @@ public enum GitHubCopilotAccountStatus: String, Codable, CustomStringConvertible case .alreadySignedIn: return "Already Signed In" case .maybeOk: - return "Maybe OK" + return "Unknown" case .notAuthorized: - return "Not Authorized" + return "No Subscription" case .notSignedIn: return "Not Signed In" case .ok: - return "OK" + return "Active" case .failedToGetToken: return "Failed to Get Token" } diff --git a/Tool/Sources/WorkspaceSuggestionService/LineEdit.swift b/Tool/Sources/WorkspaceSuggestionService/LineEdit.swift index ceea6ee..80254fa 100644 --- a/Tool/Sources/WorkspaceSuggestionService/LineEdit.swift +++ b/Tool/Sources/WorkspaceSuggestionService/LineEdit.swift @@ -54,7 +54,7 @@ public struct LineEdit { public let headEnd: String.Index public let tailStart: String.Index - static let tailChars: Set = [")", "}", "]", "\"", "'", "`"] + static let tailChars: Set = [")", ">", "}", "]", "\"", "'", "`"] /// The portion of the line to the left of the cursor. public var head: String.SubSequence {