Skip to content

Commit 630646e

Browse files
committed
Merge branch 'feature/auto-close-tabs' into develop
2 parents 3e7c947 + 0b10b54 commit 630646e

File tree

11 files changed

+115
-24
lines changed

11 files changed

+115
-24
lines changed

Copilot for Xcode.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
C89E75C32A46FB32000DD64F /* AppDelegate+Menu.swift in Sources */ = {isa = PBXBuildFile; fileRef = C89E75C22A46FB32000DD64F /* AppDelegate+Menu.swift */; };
4444
C8C8B60929AFA35F00034BEE /* CopilotForXcodeExtensionService.app in Embed XPCService */ = {isa = PBXBuildFile; fileRef = C861E60E2994F6070056CB02 /* CopilotForXcodeExtensionService.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
4545
C8DCF00029CE11D500FDDDD7 /* ChatWithSelection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */; };
46+
C8DD9CB12BC673F80036641C /* CloseIdleTabsCommand.swift in Sources */ = {isa = PBXBuildFile; fileRef = C8DD9CB02BC673F80036641C /* CloseIdleTabsCommand.swift */; };
4647
C8F1032B2A7A39D700D28F4F /* launchAgent.plist in Copy Launch Agent */ = {isa = PBXBuildFile; fileRef = C8F103292A7A365000D28F4F /* launchAgent.plist */; };
4748
/* End PBXBuildFile section */
4849

@@ -197,6 +198,7 @@
197198
C89E75C22A46FB32000DD64F /* AppDelegate+Menu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "AppDelegate+Menu.swift"; sourceTree = "<group>"; };
198199
C8CD828229B88006008D044D /* TestPlan.xctestplan */ = {isa = PBXFileReference; lastKnownFileType = text; path = TestPlan.xctestplan; sourceTree = "<group>"; };
199200
C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatWithSelection.swift; sourceTree = "<group>"; };
201+
C8DD9CB02BC673F80036641C /* CloseIdleTabsCommand.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CloseIdleTabsCommand.swift; sourceTree = "<group>"; };
200202
C8F103292A7A365000D28F4F /* launchAgent.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = launchAgent.plist; sourceTree = "<group>"; };
201203
/* End PBXFileReference section */
202204

@@ -264,6 +266,7 @@
264266
C800DBB0294C624D00B04CAC /* PrefetchSuggestionsCommand.swift */,
265267
C8758E6F29F04BFF00D29C1C /* CustomCommand.swift */,
266268
C8DCEFFF29CE11D500FDDDD7 /* ChatWithSelection.swift */,
269+
C8DD9CB02BC673F80036641C /* CloseIdleTabsCommand.swift */,
267270
C861A6A229E5503F005C41A3 /* PromptToCodeCommand.swift */,
268271
C81458972939EFDC00135263 /* Info.plist */,
269272
C81458982939EFDC00135263 /* EditorExtension.entitlements */,
@@ -525,6 +528,7 @@
525528
files = (
526529
C8DCF00029CE11D500FDDDD7 /* ChatWithSelection.swift in Sources */,
527530
C81458942939EFDC00135263 /* SourceEditorExtension.swift in Sources */,
531+
C8DD9CB12BC673F80036641C /* CloseIdleTabsCommand.swift in Sources */,
528532
C8758E7029F04BFF00D29C1C /* CustomCommand.swift in Sources */,
529533
C8758E7229F04CF100D29C1C /* SeparatorCommand.swift in Sources */,
530534
C861A6A329E5503F005C41A3 /* PromptToCodeCommand.swift in Sources */,

Core/Package.swift

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,9 @@ let package = Package(
113113
.product(name: "SuggestionModel", package: "Tool"),
114114
.product(name: "Logger", package: "Tool"),
115115
.product(name: "Preferences", package: "Tool"),
116-
]
116+
].pro([
117+
"ProClient",
118+
])
117119
),
118120
.target(
119121
name: "Service",
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Foundation
2+
import SharedUIComponents
3+
import SwiftUI
4+
5+
#if canImport(ProHostApp)
6+
import ProHostApp
7+
#endif
8+
9+
struct XcodeSettingsView: View {
10+
var body: some View {
11+
VStack {
12+
#if canImport(ProHostApp)
13+
CloseXcodeIdleTabsSettingsView()
14+
#endif
15+
16+
EmptyView()
17+
}
18+
}
19+
}
20+

Core/Sources/HostApp/FeatureSettingsView.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,16 @@ struct FeatureSettingsView: View {
3535
image: "paintbrush"
3636
)
3737

38+
ScrollView {
39+
XcodeSettingsView().padding()
40+
}
41+
.sidebarItem(
42+
tag: 3,
43+
title: "Xcode",
44+
subtitle: "Xcode related features",
45+
image: "app"
46+
)
47+
3848
// #if canImport(ProHostApp)
3949
// ScrollView {
4050
// TerminalSettingsView().padding()
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import Client
2+
import Foundation
3+
import SuggestionModel
4+
import XcodeKit
5+
6+
class CloseIdleTabsCommand: NSObject, XCSourceEditorCommand, CommandType {
7+
var name: String { "Close Idle Tabs" }
8+
9+
func perform(
10+
with invocation: XCSourceEditorCommandInvocation,
11+
completionHandler: @escaping (Error?) -> Void
12+
) {
13+
completionHandler(nil)
14+
Task {
15+
let service = try getService()
16+
_ = try await service.postNotification(name: "CloseIdleTabsOfXcodeWindow")
17+
}
18+
}
19+
}
20+

EditorExtension/SourceEditorExtension.swift

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ import Foundation
33
import Preferences
44
import XcodeKit
55

6+
#if canImport(PreferencesPlus)
7+
import PreferencesPlus
8+
#endif
9+
610
class SourceEditorExtension: NSObject, XCSourceEditorExtension {
711
var builtin: [[XCSourceEditorCommandDefinitionKey: Any]] {
812
[
@@ -17,6 +21,18 @@ class SourceEditorExtension: NSObject, XCSourceEditorExtension {
1721
].map(makeCommandDefinition)
1822
}
1923

24+
var optional: [[XCSourceEditorCommandDefinitionKey: Any]] {
25+
var all = [[XCSourceEditorCommandDefinitionKey: Any]]()
26+
27+
#if canImport(PreferencesPlus)
28+
if UserDefaults.shared.value(for: \.enableCloseIdleTabCommandInXcodeMenu) {
29+
all.append(CloseIdleTabsCommand().makeCommandDefinition())
30+
}
31+
#endif
32+
33+
return all
34+
}
35+
2036
var internalUse: [[XCSourceEditorCommandDefinitionKey: Any]] {
2137
[
2238
SeparatorCommand().named("------"),
@@ -34,7 +50,7 @@ class SourceEditorExtension: NSObject, XCSourceEditorExtension {
3450
}
3551

3652
var commandDefinitions: [[XCSourceEditorCommandDefinitionKey: Any]] {
37-
return builtin + custom + internalUse
53+
return builtin + optional + custom + internalUse
3854
}
3955

4056
func extensionDidFinishLaunching() {

Pro

Submodule Pro updated from 173f79c to 8113a55

Tool/Sources/AXExtension/AXUIElement.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ public extension AXUIElement {
2121
var value: String {
2222
(try? copyValue(key: kAXValueAttribute)) ?? ""
2323
}
24+
25+
var intValue: Int? {
26+
(try? copyValue(key: kAXValueAttribute))
27+
}
2428

2529
var title: String {
2630
(try? copyValue(key: kAXTitleAttribute)) ?? ""

Tool/Sources/Workspace/Filespace.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -92,10 +92,10 @@ public final class Filespace {
9292
// MARK: Life Cycle
9393

9494
public var isExpired: Bool {
95-
Environment.now().timeIntervalSince(lastSuggestionUpdateTime) > 60 * 3
95+
Environment.now().timeIntervalSince(lastUpdateTime) > 60 * 3
9696
}
9797

98-
private(set) var lastSuggestionUpdateTime: Date = Environment.now()
98+
public private(set) var lastUpdateTime: Date = Environment.now()
9999
private var additionalProperties = FilespacePropertyValues()
100100
let fileSaveWatcher: FileSaveWatcher
101101
let onClose: (URL) -> Void
@@ -154,7 +154,7 @@ public final class Filespace {
154154
}
155155

156156
public func refreshUpdateTime() {
157-
lastSuggestionUpdateTime = Environment.now()
157+
lastUpdateTime = Environment.now()
158158
}
159159

160160
@WorkspaceActor

Tool/Sources/Workspace/Workspace.swift

Lines changed: 33 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,9 @@ public final class Workspace {
7272
public let workspaceURL: URL
7373
public let projectRootURL: URL
7474
public let openedFileRecoverableStorage: OpenedFileRecoverableStorage
75-
public private(set) var lastSuggestionUpdateTime = Environment.now()
75+
public private(set) var lastLastUpdateTime = Environment.now()
7676
public var isExpired: Bool {
77-
Environment.now().timeIntervalSince(lastSuggestionUpdateTime) > 60 * 60 * 1
77+
Environment.now().timeIntervalSince(lastLastUpdateTime) > 60 * 60 * 1
7878
}
7979

8080
public private(set) var filespaces = [URL: Filespace]()
@@ -113,7 +113,7 @@ public final class Workspace {
113113
}
114114

115115
public func refreshUpdateTime() {
116-
lastSuggestionUpdateTime = Environment.now()
116+
lastLastUpdateTime = Environment.now()
117117
}
118118

119119
@WorkspaceActor
@@ -123,24 +123,18 @@ public final class Workspace {
123123
fileURL: fileURL,
124124
onSave: { [weak self] filespace in
125125
guard let self else { return }
126-
for plugin in self.plugins.values {
127-
plugin.didSaveFilespace(filespace)
128-
}
126+
self.didSaveFilespace(filespace)
129127
},
130128
onClose: { [weak self] url in
131129
guard let self else { return }
132-
for plugin in self.plugins.values {
133-
plugin.didCloseFilespace(url)
134-
}
130+
self.didCloseFilespace(url)
135131
}
136132
)
137133
if filespaces[fileURL] == nil {
138134
filespaces[fileURL] = filespace
139135
}
140136
if existedFilespace == nil {
141-
for plugin in plugins.values {
142-
plugin.didOpenFilespace(filespace)
143-
}
137+
didOpenFilespace(filespace)
144138
} else {
145139
filespace.refreshUpdateTime()
146140
}
@@ -154,10 +148,37 @@ public final class Workspace {
154148

155149
@WorkspaceActor
156150
public func didUpdateFilespace(fileURL: URL, content: String) {
151+
refreshUpdateTime()
157152
guard let filespace = filespaces[fileURL] else { return }
153+
filespace.refreshUpdateTime()
158154
for plugin in plugins.values {
159155
plugin.didUpdateFilespace(filespace, content: content)
160156
}
161157
}
158+
159+
@WorkspaceActor
160+
func didOpenFilespace(_ filespace: Filespace) {
161+
refreshUpdateTime()
162+
openedFileRecoverableStorage.openFile(fileURL: filespace.fileURL)
163+
for plugin in plugins.values {
164+
plugin.didOpenFilespace(filespace)
165+
}
166+
}
167+
168+
@WorkspaceActor
169+
func didCloseFilespace(_ fileURL: URL) {
170+
for plugin in self.plugins.values {
171+
plugin.didCloseFilespace(fileURL)
172+
}
173+
}
174+
175+
@WorkspaceActor
176+
func didSaveFilespace(_ filespace: Filespace) {
177+
refreshUpdateTime()
178+
filespace.refreshUpdateTime()
179+
for plugin in plugins.values {
180+
plugin.didSaveFilespace(filespace)
181+
}
182+
}
162183
}
163184

0 commit comments

Comments
 (0)