Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 82d39cc

Browse files
Improve LSP Install UX (#2101)
### Description Implements an installing progress view for language servers from the mason registry. - Package managers have been reworked to return a list of 'steps' to execute. - Created a model for running steps and waiting for confirmation if required before a step. - Added UI that observes the running model for executed steps and output, as well as errors. ### Related Issues * #1997 ### Checklist - [x] I read and understood the [contributing guide](https://github.com/CodeEditApp/CodeEdit/blob/main/CONTRIBUTING.md) as well as the [code of conduct](https://github.com/CodeEditApp/CodeEdit/blob/main/CODE_OF_CONDUCT.md) - [x] The issues this PR addresses are related to each other - [x] My changes generate no new warnings - [x] My code builds and runs on my machine - [x] My changes are all related to the related issue above - [x] I documented my code ### Screenshots https://github.com/user-attachments/assets/6f0f8a62-1034-4c15-bebe-8d01fff0019e
1 parent bdf21ac commit 82d39cc

39 files changed

+2023
-1194
lines changed

‎CodeEdit/Features/ActivityViewer/Notifications/TaskNotificationHandler.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,7 @@ final class TaskNotificationHandler: ObservableObject {
132132
/// - toWorkspace: The workspace to restrict the task to. Defaults to `nil`, which is received by all workspaces.
133133
/// - action: The action being taken on the task.
134134
/// - model: The task contents.
135+
@MainActor
135136
static func postTask(toWorkspace: URL? = nil, action: Action, model: TaskNotificationModel) {
136137
NotificationCenter.default.post(name: .taskNotification, object: nil, userInfo: [
137138
"id": model.id,
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
//
2+
// ErrorDescriptionLabel.swift
3+
// CodeEdit
4+
//
5+
// Created by Khan Winter on 8/14/25.
6+
//
7+
8+
import SwiftUI
9+
10+
struct ErrorDescriptionLabel: View {
11+
let error: Error
12+
13+
var body: some View {
14+
VStack(alignment: .leading) {
15+
if let error = error as? LocalizedError {
16+
if let description = error.errorDescription {
17+
Text(description)
18+
}
19+
20+
if let reason = error.failureReason {
21+
Text(reason)
22+
}
23+
24+
if let recoverySuggestion = error.recoverySuggestion {
25+
Text(recoverySuggestion)
26+
}
27+
} else {
28+
Text(error.localizedDescription)
29+
}
30+
}
31+
}
32+
}
33+
34+
#Preview {
35+
ErrorDescriptionLabel(error: CancellationError())
36+
}
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
//
2+
// PackageManagerError.swift
3+
// CodeEdit
4+
//
5+
// Created by Abe Malla on 5/12/25.
6+
//
7+
8+
import Foundation
9+
10+
enum PackageManagerError: Error, LocalizedError {
11+
case unknown
12+
case packageManagerNotInstalled
13+
case initializationFailed(String)
14+
case installationFailed(String)
15+
case invalidConfiguration
16+
17+
var errorDescription: String? {
18+
switch self {
19+
case .unknown:
20+
"Unknown error occurred"
21+
case .packageManagerNotInstalled:
22+
"The required package manager is not installed."
23+
case .initializationFailed:
24+
"Installation directory initialization failed."
25+
case .installationFailed:
26+
"Package installation failed."
27+
case .invalidConfiguration:
28+
"The package registry contained an invalid installation configuration."
29+
}
30+
}
31+
32+
var failureReason: String? {
33+
switch self {
34+
case .unknown:
35+
nil
36+
case .packageManagerNotInstalled:
37+
nil
38+
case .initializationFailed(let string):
39+
string
40+
case .installationFailed(let string):
41+
string
42+
case .invalidConfiguration:
43+
nil
44+
}
45+
}
46+
}
Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
//
2+
// RegistryManagerError.swift
3+
// CodeEdit
4+
//
5+
// Created by Abe Malla on 5/12/25.
6+
//
7+
8+
import Foundation
9+
10+
enum RegistryManagerError: Error, LocalizedError {
11+
case installationRunning
12+
case invalidResponse(statusCode: Int)
13+
case downloadFailed(url: URL, error: Error)
14+
case maxRetriesExceeded(url: URL, lastError: Error)
15+
case writeFailed(error: Error)
16+
case failedToSaveRegistryCache
17+
18+
var errorDescription: String? {
19+
switch self {
20+
case .installationRunning:
21+
"A package is already being installed."
22+
case .invalidResponse(let statusCode):
23+
"Invalid response received: \(statusCode)"
24+
case .downloadFailed(let url, _):
25+
"Download for \(url) error."
26+
case .maxRetriesExceeded(let url, _):
27+
"Maximum retries exceeded for url: \(url)"
28+
case .writeFailed:
29+
"Failed to write to file."
30+
case .failedToSaveRegistryCache:
31+
"Failed to write to registry cache."
32+
}
33+
}
34+
35+
var failureReason: String? {
36+
switch self {
37+
case .installationRunning, .invalidResponse, .failedToSaveRegistryCache:
38+
return nil
39+
case .downloadFailed(_, let error), .maxRetriesExceeded(_, let error), .writeFailed(let error):
40+
return if let error = error as? LocalizedError {
41+
error.errorDescription
42+
} else {
43+
error.localizedDescription
44+
}
45+
}
46+
}
47+
}

‎CodeEdit/Features/LSP/Registry/InstallationQueueManager.swift

Lines changed: 0 additions & 185 deletions
This file was deleted.

‎CodeEdit/Features/LSP/Registry/InstallationMethod.swift renamed to ‎CodeEdit/Features/LSP/Registry/Model/InstallationMethod.swift

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,42 @@ enum InstallationMethod: Equatable {
5050
return nil
5151
}
5252
}
53+
54+
func packageManager(installPath: URL) -> PackageManagerProtocol? {
55+
switch packageManagerType {
56+
case .npm:
57+
return NPMPackageManager(installationDirectory: installPath)
58+
case .cargo:
59+
return CargoPackageManager(installationDirectory: installPath)
60+
case .pip:
61+
return PipPackageManager(installationDirectory: installPath)
62+
case .golang:
63+
return GolangPackageManager(installationDirectory: installPath)
64+
case .github, .sourceBuild:
65+
return GithubPackageManager(installationDirectory: installPath)
66+
case .nuget, .opam, .gem, .composer:
67+
// TODO: IMPLEMENT OTHER PACKAGE MANAGERS
68+
return nil
69+
default:
70+
return nil
71+
}
72+
}
73+
74+
var installerDescription: String {
75+
guard let packageManagerType else { return "Unknown" }
76+
switch packageManagerType {
77+
case .npm, .cargo, .golang, .pip, .sourceBuild, .github:
78+
return packageManagerType.userDescription
79+
case .nuget, .opam, .gem, .composer:
80+
return "(Unsupported) \(packageManagerType.userDescription)"
81+
}
82+
}
83+
84+
var packageDescription: String? {
85+
guard let packageName else { return nil }
86+
if let version {
87+
return "\(packageName)@\(version)"
88+
}
89+
return packageName
90+
}
5391
}

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /