diff --git a/Copilot for Xcode/App.swift b/Copilot for Xcode/App.swift
index bd7df55..a00e4f2 100644
--- a/Copilot for Xcode/App.swift
+++ b/Copilot for Xcode/App.swift
@@ -27,7 +27,6 @@ struct CopilotForXcodeApp: App {
.onAppear {
UserDefaults.setupDefaultSettings()
}
- .environment(\.updateChecker, UpdateChecker(hostBundle: Bundle.main))
.copilotIntroSheet()
}
}
diff --git a/Copilot-for-Xcode-Info.plist b/Copilot-for-Xcode-Info.plist
index a128dc2..05fd996 100644
--- a/Copilot-for-Xcode-Info.plist
+++ b/Copilot-for-Xcode-Info.plist
@@ -1,30 +1,32 @@
-
-
- $(AppIdentifierPrefix)
- APPLICATION_SUPPORT_FOLDER
- $(APPLICATION_SUPPORT_FOLDER)
- BUNDLE_IDENTIFIER_BASE
- $(BUNDLE_IDENTIFIER_BASE)
- EXTENSION_BUNDLE_NAME
- $(EXTENSION_BUNDLE_NAME)
- HOST_APP_NAME
- $(HOST_APP_NAME)
- LANGUAGE_SERVER_PATH
- $(LANGUAGE_SERVER_PATH)
- NODE_PATH
- $(NODE_PATH)
- SUEnableAutomaticChecks
- YES
- SUEnableJavaScript
- NO
- SUFeedURL
- $(SPARKLE_FEED_URL)
- SUPublicEDKey
- $(SPARKLE_PUBLIC_KEY)
- TEAM_ID_PREFIX
- $(TeamIdentifierPrefix)
-
+
+
+ $(AppIdentifierPrefix)
+ APPLICATION_SUPPORT_FOLDER
+ $(APPLICATION_SUPPORT_FOLDER)
+ BUNDLE_IDENTIFIER_BASE
+ $(BUNDLE_IDENTIFIER_BASE)
+ EXTENSION_BUNDLE_NAME
+ $(EXTENSION_BUNDLE_NAME)
+ HOST_APP_NAME
+ $(HOST_APP_NAME)
+ LANGUAGE_SERVER_PATH
+ $(LANGUAGE_SERVER_PATH)
+ NODE_PATH
+ $(NODE_PATH)
+ SUEnableAutomaticChecks
+ YES
+ SUScheduledCheckInterval
+ 3600
+ SUEnableJavaScript
+ NO
+ SUFeedURL
+ $(SPARKLE_FEED_URL)
+ SUPublicEDKey
+ $(SPARKLE_PUBLIC_KEY)
+ TEAM_ID_PREFIX
+ $(TeamIdentifierPrefix)
+
diff --git a/Core/Sources/HostApp/FeatureSettings/LoggingSettingsView.swift b/Core/Sources/HostApp/FeatureSettings/LoggingSettingsView.swift
new file mode 100644
index 0000000..da311de
--- /dev/null
+++ b/Core/Sources/HostApp/FeatureSettings/LoggingSettingsView.swift
@@ -0,0 +1,63 @@
+import AppKit
+import Logger
+import Preferences
+import SwiftUI
+
+struct LoggingSettingsView: View {
+ @AppStorage(\.verboseLoggingEnabled) var verboseLoggingEnabled: Bool
+ @State private var shouldPresentRestartAlert = false
+
+ var body: some View {
+ VStack(alignment: .leading) {
+ Text("Logging")
+ .bold()
+ .padding(.leading, 8)
+ VStack(spacing: .zero) {
+ HStack(alignment: .center) {
+ Text("Verbose Logging")
+ .padding(.horizontal, 8)
+ Spacer()
+ Toggle(isOn: $verboseLoggingEnabled) {
+ }
+ .toggleStyle(.switch)
+ .padding(.horizontal, 8)
+ }
+ .padding(.vertical, 8)
+ .onChange(of: verboseLoggingEnabled) { _ in
+ shouldPresentRestartAlert = true
+ }
+
+ Divider()
+
+ HStack {
+ Text("Open Copilot Log Folder")
+ .font(.body)
+ Spacer()
+ Image(systemName: "chevron.right")
+ }
+ .onTapGesture {
+ NSWorkspace.shared.open(URL(fileURLWithPath: FileLoggingLocation.path.string, isDirectory: true))
+ }
+ .foregroundStyle(.primary)
+ .padding(.horizontal, 8)
+ .padding(.vertical, 10)
+ }
+ .background(Color.gray.opacity(0.1))
+ .cornerRadius(8)
+ }
+ .padding(.horizontal, 20)
+ .alert(isPresented: $shouldPresentRestartAlert) {
+ Alert(
+ title: Text("Quit And Restart Xcode"),
+ message: Text(
+ """
+ Logging level changes will take effect the next time Copilot \
+ for Xcode is started. To update logging now, please quit \
+ Copilot for Xcode and restart Xcode.
+ """
+ ),
+ dismissButton: .default(Text("OK"))
+ )
+ }
+ }
+}
diff --git a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggesionSettingProxyView.swift b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggesionSettingProxyView.swift
index 7f8488c..9388cbb 100644
--- a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggesionSettingProxyView.swift
+++ b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggesionSettingProxyView.swift
@@ -6,7 +6,6 @@ import Toast
import Client
struct SuggesionSettingProxyView: View {
-
class Settings: ObservableObject {
@AppStorage("username") var username: String = ""
@AppStorage(\.gitHubCopilotProxyUrl) var gitHubCopilotProxyUrl
@@ -14,8 +13,6 @@ struct SuggesionSettingProxyView: View {
@AppStorage(\.gitHubCopilotProxyPassword) var gitHubCopilotProxyPassword
@AppStorage(\.gitHubCopilotUseStrictSSL) var gitHubCopilotUseStrictSSL
@AppStorage(\.gitHubCopilotEnterpriseURI) var gitHubCopilotEnterpriseURI
-
- init() {}
}
@StateObject var settings = Settings()
@@ -23,48 +20,98 @@ struct SuggesionSettingProxyView: View {
var body: some View {
VStack(alignment: .leading) {
- SettingsDivider("Enterprise")
+ Text(StringConstants.enterprise)
+ .bold()
+ .padding(.leading, 8)
Form {
TextField(
text: $settings.gitHubCopilotEnterpriseURI,
- prompt: Text("Leave it blank if none is available.")
+ prompt: Text(StringConstants.leaveBlankPrompt)
) {
- Text("Auth provider URL")
+ Text(StringConstants.authProviderURL)
}
+ .textFieldStyle(PlainTextFieldStyle())
+ .multilineTextAlignment(.trailing)
}
+ .padding(8)
+ .background(Color.gray.opacity(0.1))
+ .cornerRadius(6)
+ .padding(.bottom, 16)
- SettingsDivider("Proxy")
+ Text(StringConstants.proxy)
+ .bold()
+ .padding(.leading, 8)
- Form {
- TextField(
- text: $settings.gitHubCopilotProxyUrl,
- prompt: Text("http://host:port")
- ) {
- Text("Proxy URL")
+ VStack(spacing: 0) {
+ Form {
+ TextField(
+ text: $settings.gitHubCopilotProxyUrl,
+ prompt: Text(StringConstants.proxyURLPrompt)
+ ) {
+ Text(StringConstants.proxyURL)
+ }
+ .textFieldStyle(PlainTextFieldStyle())
+ .multilineTextAlignment(.trailing)
}
- TextField(text: $settings.gitHubCopilotProxyUsername) {
- Text("Proxy username")
+ .padding(.horizontal, 16)
+ .padding(.vertical, 8)
+
+ Divider()
+
+ Form {
+ TextField(text: $settings.gitHubCopilotProxyUsername, prompt: Text(StringConstants.proxyUsernamePrompt)) {
+ Text(StringConstants.proxyUsername)
+ }
+ .textFieldStyle(PlainTextFieldStyle())
+ .multilineTextAlignment(.trailing)
}
- SecureField(text: $settings.gitHubCopilotProxyPassword) {
- Text("Proxy password")
+ .padding(.horizontal, 16)
+ .padding(.vertical, 8)
+
+ Divider()
+
+ Form {
+ SecureField(text: $settings.gitHubCopilotProxyPassword, prompt: Text(StringConstants.proxyPasswordPrompt)) {
+ Text(StringConstants.proxyPassword)
+ }
+ .textFieldStyle(PlainTextFieldStyle())
+ .multilineTextAlignment(.trailing)
}
- Toggle("Proxy strict SSL", isOn: $settings.gitHubCopilotUseStrictSSL)
+ .padding(.horizontal, 16)
+ .padding(.vertical, 8)
+
+ Divider()
- Button("Refresh configurations") {
+ HStack {
+ Text(StringConstants.proxyStrictSSL)
+ Spacer()
+ Toggle("", isOn: $settings.gitHubCopilotUseStrictSSL)
+ .toggleStyle(.switch)
+ }
+ .padding(.horizontal, 16)
+ .padding(.vertical, 8)
+ }
+ .background(Color.gray.opacity(0.1))
+ .cornerRadius(6)
+ .padding(.bottom, 8)
+
+ HStack {
+ Spacer()
+ Button(StringConstants.refreshConfigurations) {
refreshConfiguration()
- }.padding(.top, 6)
+ }
}
+ .padding(.horizontal, 16)
+ Spacer()
}
- .textFieldStyle(.roundedBorder)
+ .padding(16)
}
-
func refreshConfiguration() {
NotificationCenter.default.post(
name: .gitHubCopilotShouldRefreshEditorInformation,
object: nil
)
-
Task {
let service = try getService()
do {
diff --git a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsGeneralSectionView.swift b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsGeneralSectionView.swift
index 35f7caa..debc7c8 100644
--- a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsGeneralSectionView.swift
+++ b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsGeneralSectionView.swift
@@ -6,39 +6,62 @@ import XPCShared
struct SuggestionSettingsGeneralSectionView: View {
final class Settings: ObservableObject {
- @AppStorage(\.realtimeSuggestionToggle)
- var realtimeSuggestionToggle
- @AppStorage(\.suggestionFeatureEnabledProjectList)
- var suggestionFeatureEnabledProjectList
- @AppStorage(\.acceptSuggestionWithTab)
- var acceptSuggestionWithTab
+ @AppStorage(\.realtimeSuggestionToggle) var realtimeSuggestionToggle
+ @AppStorage(\.suggestionFeatureEnabledProjectList) var suggestionFeatureEnabledProjectList
+ @AppStorage(\.acceptSuggestionWithTab) var acceptSuggestionWithTab
}
@StateObject var settings = Settings()
@State var isSuggestionFeatureDisabledLanguageListViewOpen = false
var body: some View {
- Form {
- Toggle(isOn: $settings.realtimeSuggestionToggle) {
- Text("Request suggestions in real-time")
- }
+ VStack(alignment: .leading) {
+ Text(StringConstants.suggestionSettings)
+ .bold()
+ .padding(.leading, 8)
+
+ VStack(spacing: .zero) {
+ HStack(alignment: .center) {
+ Text(StringConstants.requestSuggestionsInRealTime)
+ .padding(.horizontal, 8)
+ Spacer()
+ Toggle(isOn: $settings.realtimeSuggestionToggle) {
+ }
+ .toggleStyle(SwitchToggleStyle(tint: .blue))
+ .padding(.horizontal, 8)
+ }
+ .padding(.vertical, 8)
- Toggle(isOn: $settings.acceptSuggestionWithTab) {
- HStack {
- Text("Accept suggestions with Tab")
+ Divider()
+
+ HStack(alignment: .center) {
+ Text(StringConstants.acceptSuggestionsWithTab)
+ .padding(.horizontal, 8)
+ Spacer()
+ Toggle(isOn: $settings.acceptSuggestionWithTab) {
+ }
+ .toggleStyle(SwitchToggleStyle(tint: .blue))
+ .padding(.horizontal, 8)
}
+ .padding(.vertical, 8)
}
+ .background(Color.gray.opacity(0.1))
+ .cornerRadius(6)
+ .padding(.bottom, 8)
HStack {
- Button("Disabled language list") {
+ Spacer()
+ Button(StringConstants.disabledLanguageList) {
isSuggestionFeatureDisabledLanguageListViewOpen = true
}
- }.sheet(isPresented: $isSuggestionFeatureDisabledLanguageListViewOpen) {
- SuggestionFeatureDisabledLanguageListView(
- isOpen: $isSuggestionFeatureDisabledLanguageListViewOpen
- )
}
+ .padding(.horizontal)
+ .sheet(isPresented: $isSuggestionFeatureDisabledLanguageListViewOpen) {
+ SuggestionFeatureDisabledLanguageListView(isOpen: $isSuggestionFeatureDisabledLanguageListViewOpen)
+ }
+ Spacer()
}
+ .padding(16)
}
}
diff --git a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsView.swift b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsView.swift
index f5a99ac..8d2f05a 100644
--- a/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsView.swift
+++ b/Core/Sources/HostApp/FeatureSettings/Suggestion/SuggestionSettingsView.swift
@@ -9,6 +9,7 @@ struct SuggestionSettingsView: View {
ScrollView {
SuggestionSettingsGeneralSectionView()
SuggesionSettingProxyView()
+ LoggingSettingsView()
}.padding()
}
}
diff --git a/Core/Sources/HostApp/StringConstants.swift b/Core/Sources/HostApp/StringConstants.swift
index 5740f0f..ca47928 100644
--- a/Core/Sources/HostApp/StringConstants.swift
+++ b/Core/Sources/HostApp/StringConstants.swift
@@ -1,4 +1,5 @@
struct StringConstants {
+ // General Tab Strings
static let rightsReserved = "GitHub. All rights reserved."
static let appName = "GitHub Copilot for Xcode"
static let languageServerVersion = "Language Server Version:"
@@ -28,4 +29,24 @@ struct StringConstants {
static let copilotDocumentation = "View Copilot Documentation"
static let copilotFeedbackForum = "View Copilot Feedback Forum"
static let loading = "Loading.."
+
+// Feature Tab Settings Strings
+ static let suggestionSettings = "Suggestion Settings"
+ static let requestSuggestionsInRealTime = "Request suggestions in real-time"
+ static let acceptSuggestionsWithTab = "Accept suggestions with Tab"
+ static let disabledLanguageList = "Disabled language list"
+
+ // Proxy String
+ static let enterprise = "Enterprise"
+ static let leaveBlankPrompt = "Leave it blank if none is available."
+ static let authProviderURL = "Auth provider URL"
+ static let proxy = "Proxy"
+ static let proxyURLPrompt = "http://host:port"
+ static let proxyURL = "Proxy URL"
+ static let proxyUsernamePrompt = "username"
+ static let proxyUsername = "Proxy username"
+ static let proxyPasswordPrompt = "password"
+ static let proxyPassword = "Proxy password"
+ static let proxyStrictSSL = "Proxy strict SSL"
+ static let refreshConfigurations = "Refresh configurations"
}
diff --git a/Core/Sources/HostApp/TabContainer.swift b/Core/Sources/HostApp/TabContainer.swift
index e40db63..b60cc48 100644
--- a/Core/Sources/HostApp/TabContainer.swift
+++ b/Core/Sources/HostApp/TabContainer.swift
@@ -40,8 +40,8 @@ public struct TabContainer: View {
)
FeatureSettingsView().tabBarItem(
tag: 2,
- title: "Feature",
- image: "star.circle"
+ title: "Advanced",
+ image: "gearshape.2.fill"
)
}
.environment(\.tabBarTabTag, tag)
@@ -201,7 +201,7 @@ private extension EnvironmentValues {
}
struct UpdateCheckerKey: EnvironmentKey {
- static var defaultValue: UpdateChecker = .init(hostBundle: nil)
+ static var defaultValue: UpdateChecker = .init(hostBundle: Bundle.main)
}
public extension EnvironmentValues {
diff --git a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotService.swift b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotService.swift
index 4b947b9..6267fb6 100644
--- a/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotService.swift
+++ b/Tool/Sources/GitHubCopilotService/LanguageServer/GitHubCopilotService.swift
@@ -146,7 +146,11 @@ public class GitHubCopilotBaseService {
// Set debug port and verbose when running in debug
let environment: [String: String] = ["HOME": home, "GH_COPILOT_DEBUG_UI_PORT": "8080", "GH_COPILOT_VERBOSE": "true"]
#else
- let environment: [String: String] = ["HOME": home]
+ let environment: [String: String] = if UserDefaults.shared.value(for: \.verboseLoggingEnabled) {
+ ["HOME": home, "GH_COPILOT_VERBOSE": "true"]
+ } else {
+ ["HOME": home]
+ }
#endif
let executionParams = Process.ExecutionParameters(
diff --git a/Tool/Sources/Logger/FileLogger.swift b/Tool/Sources/Logger/FileLogger.swift
index 85f85f9..e7c2a64 100644
--- a/Tool/Sources/Logger/FileLogger.swift
+++ b/Tool/Sources/Logger/FileLogger.swift
@@ -1,6 +1,15 @@
import Foundation
import System
+public final class FileLoggingLocation {
+ public static let path = {
+ FilePath(stringLiteral: NSHomeDirectory())
+ .appending("Library")
+ .appending("Logs")
+ .appending("GitHubCopilot")
+ }()
+}
+
final class FileLogger {
private let timestampFormat = Date.ISO8601FormatStyle.iso8601
.year()
@@ -38,10 +47,7 @@ actor FileLoggerImplementation {
private var logHandle: FileHandle?
public init() {
- logDir = FilePath(stringLiteral: NSHomeDirectory())
- .appending("Library")
- .appending("Logs")
- .appending("GitHubCopilot")
+ logDir = FileLoggingLocation.path
logName = "\(logBaseName).\(logExtension)"
lockFilePath = logDir.appending(logName + ".lock")
}
diff --git a/Tool/Sources/Preferences/Keys.swift b/Tool/Sources/Preferences/Keys.swift
index 4772feb..3e4a4c1 100644
--- a/Tool/Sources/Preferences/Keys.swift
+++ b/Tool/Sources/Preferences/Keys.swift
@@ -527,27 +527,31 @@ public extension UserDefaultPreferenceKeys {
}
}
-// MARK: - Feature
+// MARK: - Advanced Features
public extension UserDefaultPreferenceKeys {
var gitHubCopilotProxyUrl: PreferenceKey {
.init(defaultValue: "", key: "GitHubCopilotProxyUrl")
}
-
+
var gitHubCopilotUseStrictSSL: PreferenceKey {
.init(defaultValue: true, key: "GitHubCopilotUseStrictSSL")
}
-
+
var gitHubCopilotProxyUsername: PreferenceKey {
.init(defaultValue: "", key: "GitHubCopilotProxyUsername")
}
-
+
var gitHubCopilotProxyPassword: PreferenceKey {
.init(defaultValue: "", key: "GitHubCopilotProxyPassword")
}
-
+
var gitHubCopilotEnterpriseURI: PreferenceKey {
.init(defaultValue: "", key: "GitHubCopilotEnterpriseURI")
}
+
+ var verboseLoggingEnabled: PreferenceKey {
+ .init(defaultValue: false, key: "VerboseLoggingEnabled")
+ }
}