Skip to content

Commit b839c1a

Browse files
committed
Added an Internal Development Inspector for debug purposes. This inspector can be enabled with a setting found in the hidden developer settings page.
1 parent 721389c commit b839c1a

File tree

6 files changed

+190
-11
lines changed

6 files changed

+190
-11
lines changed

CodeEdit.xcodeproj/project.pbxproj

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,7 @@
528528
B6152B802ADAE421004C6012 /* CodeEditWindowControllerExtensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = B6152B7F2ADAE421004C6012 /* CodeEditWindowControllerExtensions.swift */; };
529529
B616EA882D651ADA00DF9029 /* ScrollOffsetPreferenceKey.swift in Sources */ = {isa = PBXBuildFile; fileRef = B616EA872D651ADA00DF9029 /* ScrollOffsetPreferenceKey.swift */; };
530530
B616EA892D651ADA00DF9029 /* OverlayButtonStyle.swift in Sources */ = {isa = PBXBuildFile; fileRef = B616EA862D651ADA00DF9029 /* OverlayButtonStyle.swift */; };
531+
B616EA8D2D65238900DF9029 /* InternalDevelopmentInspectorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B616EA8B2D65238900DF9029 /* InternalDevelopmentInspectorView.swift */; };
531532
B61A606129F188AB009B43F9 /* ExternalLink.swift in Sources */ = {isa = PBXBuildFile; fileRef = B61A606029F188AB009B43F9 /* ExternalLink.swift */; };
532533
B61A606929F4481A009B43F9 /* MonospacedFontPicker.swift in Sources */ = {isa = PBXBuildFile; fileRef = B61A606829F4481A009B43F9 /* MonospacedFontPicker.swift */; };
533534
B61DA9DF29D929E100BF4A43 /* GeneralSettingsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B61DA9DE29D929E100BF4A43 /* GeneralSettingsView.swift */; };
@@ -1222,6 +1223,7 @@
12221223
B6152B7F2ADAE421004C6012 /* CodeEditWindowControllerExtensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CodeEditWindowControllerExtensions.swift; sourceTree = "<group>"; };
12231224
B616EA862D651ADA00DF9029 /* OverlayButtonStyle.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OverlayButtonStyle.swift; sourceTree = "<group>"; };
12241225
B616EA872D651ADA00DF9029 /* ScrollOffsetPreferenceKey.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ScrollOffsetPreferenceKey.swift; sourceTree = "<group>"; };
1226+
B616EA8B2D65238900DF9029 /* InternalDevelopmentInspectorView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InternalDevelopmentInspectorView.swift; sourceTree = "<group>"; };
12251227
B61A606029F188AB009B43F9 /* ExternalLink.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExternalLink.swift; sourceTree = "<group>"; };
12261228
B61A606829F4481A009B43F9 /* MonospacedFontPicker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MonospacedFontPicker.swift; sourceTree = "<group>"; };
12271229
B61DA9DE29D929E100BF4A43 /* GeneralSettingsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GeneralSettingsView.swift; sourceTree = "<group>"; };
@@ -3282,6 +3284,14 @@
32823284
path = Styles;
32833285
sourceTree = "<group>";
32843286
};
3287+
B616EA8C2D65238900DF9029 /* InternalDevelopmentInspector */ = {
3288+
isa = PBXGroup;
3289+
children = (
3290+
B616EA8B2D65238900DF9029 /* InternalDevelopmentInspectorView.swift */,
3291+
);
3292+
path = InternalDevelopmentInspector;
3293+
sourceTree = "<group>";
3294+
};
32853295
B61DA9DD29D929BF00BF4A43 /* Pages */ = {
32863296
isa = PBXGroup;
32873297
children = (
@@ -3765,6 +3775,7 @@
37653775
3026F50B2AC006A10061227E /* ViewModels */,
37663776
B67660672AA972B000CD56B0 /* FileInspector */,
37673777
B67660662AA9726F00CD56B0 /* HistoryInspector */,
3778+
B616EA8C2D65238900DF9029 /* InternalDevelopmentInspector */,
37683779
20EBB50B280C382800F3A5DA /* Models */,
37693780
20EBB4FF280C325000F3A5DA /* Views */,
37703781
);
@@ -4183,6 +4194,7 @@
41834194
587B9E8829301D8F00AC7927 /* GitHubFiles.swift in Sources */,
41844195
587B9DA729300ABD00AC7927 /* HelpButton.swift in Sources */,
41854196
77EF6C0B2C60C80800984B69 /* URL+Filename.swift in Sources */,
4197+
B616EA8D2D65238900DF9029 /* InternalDevelopmentInspectorView.swift in Sources */,
41864198
30B088172C0D53080063A882 /* LSPUtil.swift in Sources */,
41874199
6C5B63DE29C76213005454BA /* WindowCodeFileView.swift in Sources */,
41884200
58F2EB08292FB2B0004A9BDE /* TextEditingSettings.swift in Sources */,
Lines changed: 130 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,130 @@
1+
import SwiftUI
2+
3+
struct InternalDevelopmentInspectorView: View {
4+
var body: some View {
5+
Form {
6+
Section("Test Notifications") {
7+
Button("Add Notification") {
8+
let (iconSymbol, iconColor) = randomSymbolAndColor()
9+
NotificationManager.shared.post(
10+
iconSymbol: iconSymbol,
11+
iconColor: iconColor,
12+
title: "Test Notification",
13+
description: "This is a test notification.",
14+
actionButtonTitle: "Action",
15+
action: {
16+
print("Test notification action triggered")
17+
}
18+
)
19+
}
20+
Button("Add Sticky Notification") {
21+
NotificationManager.shared.post(
22+
iconSymbol: "pin.fill",
23+
iconColor: .orange,
24+
title: "Sticky Notification",
25+
description: "This notification will stay until dismissed.",
26+
actionButtonTitle: "Acknowledge",
27+
action: {
28+
print("Sticky notification acknowledged")
29+
},
30+
isSticky: true
31+
)
32+
}
33+
Button("Add Image Notification") {
34+
NotificationManager.shared.post(
35+
iconImage: randomImage(),
36+
title: "Test Notification with Image",
37+
description: "This is a test notification with a custom image.",
38+
actionButtonTitle: "Action",
39+
action: {
40+
print("Test notification action triggered")
41+
}
42+
)
43+
}
44+
Button("Add Text Notification") {
45+
NotificationManager.shared.post(
46+
iconText: randomLetter(),
47+
iconTextColor: .white,
48+
iconColor: randomColor(),
49+
title: "Text Notification",
50+
description: "This is a test notification with text.",
51+
actionButtonTitle: "Acknowledge",
52+
action: {
53+
print("Test notification action triggered")
54+
}
55+
)
56+
}
57+
Button("Add Emoji Notification") {
58+
NotificationManager.shared.post(
59+
iconText: randomEmoji(),
60+
iconTextColor: .white,
61+
iconColor: randomColor(),
62+
title: "Emoji Notification",
63+
description: "This is a test notification with an emoji.",
64+
actionButtonTitle: "Acknowledge",
65+
action: {
66+
print("Test notification action triggered")
67+
}
68+
)
69+
}
70+
}
71+
}
72+
}
73+
74+
// Helper functions moved from FileInspectorView
75+
private func randomColor() -> Color {
76+
let colors: [Color] = [
77+
.red, .orange, .yellow, .green, .mint, .cyan,
78+
.teal, .blue, .indigo, .purple, .pink, .gray
79+
]
80+
return colors.randomElement() ?? .black
81+
}
82+
83+
private func randomSymbolAndColor() -> (String, Color) {
84+
let symbols: [(String, Color)] = [
85+
("bell.fill", .red),
86+
("bell.badge.fill", .red),
87+
("exclamationmark.triangle.fill", .orange),
88+
("info.circle.fill", .blue),
89+
("checkmark.seal.fill", .green),
90+
("xmark.octagon.fill", .red),
91+
("bubble.left.fill", .teal),
92+
("envelope.fill", .blue),
93+
("phone.fill", .green),
94+
("megaphone.fill", .pink),
95+
("clock.fill", .gray),
96+
("calendar", .red),
97+
("flag.fill", .green),
98+
("bookmark.fill", .orange),
99+
("bolt.fill", .indigo),
100+
("shield.lefthalf.fill", .red),
101+
("gift.fill", .purple),
102+
("heart.fill", .pink),
103+
("star.fill", .orange),
104+
("curlybraces", .cyan),
105+
]
106+
return symbols.randomElement() ?? ("bell.fill", .red)
107+
}
108+
109+
private func randomEmoji() -> String {
110+
let emoji: [String] = [
111+
"🔔", "🚨", "⚠️", "👋", "😍", "😎", "😘", "😜", "😝", "😀", "😁",
112+
"😂", "🤣", "😃", "😄", "😅", "😆", "😇", "😉", "😊", "😋", "😌"
113+
]
114+
return emoji.randomElement() ?? "🔔"
115+
}
116+
117+
private func randomImage() -> Image {
118+
let images: [Image] = [
119+
Image("GitHubIcon"),
120+
Image("BitBucketIcon"),
121+
Image("GitLabIcon")
122+
]
123+
return images.randomElement() ?? Image("GitHubIcon")
124+
}
125+
126+
private func randomLetter() -> String {
127+
let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ".map { String($0) }
128+
return letters.randomElement() ?? "A"
129+
}
130+
}

CodeEdit/Features/InspectorArea/Models/InspectorTab.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import ExtensionFoundation
1212
enum InspectorTab: WorkspacePanelTab {
1313
case file
1414
case gitHistory
15+
case internalDevelopment
1516
case uiExtension(endpoint: AppExtensionIdentity, data: ResolvedSidebar.SidebarStore)
1617

1718
var systemImage: String {
@@ -20,6 +21,8 @@ enum InspectorTab: WorkspacePanelTab {
2021
return "doc"
2122
case .gitHistory:
2223
return "clock"
24+
case .internalDevelopment:
25+
return "hammer"
2326
case .uiExtension(_, let data):
2427
return data.icon ?? "e.square"
2528
}
@@ -38,6 +41,8 @@ enum InspectorTab: WorkspacePanelTab {
3841
return "File Inspector"
3942
case .gitHistory:
4043
return "History Inspector"
44+
case .internalDevelopment:
45+
return "Internal Development"
4146
case .uiExtension(_, let data):
4247
return data.help ?? data.sceneID
4348
}
@@ -49,6 +54,8 @@ enum InspectorTab: WorkspacePanelTab {
4954
FileInspectorView()
5055
case .gitHistory:
5156
HistoryInspectorView()
57+
case .internalDevelopment:
58+
InternalDevelopmentInspectorView()
5259
case let .uiExtension(endpoint, data):
5360
ExtensionSceneView(with: endpoint, sceneID: data.sceneID)
5461
}

CodeEdit/Features/InspectorArea/Views/InspectorAreaView.swift

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -16,21 +16,32 @@ struct InspectorAreaView: View {
1616
@AppSettings(\.general.inspectorTabBarPosition)
1717
var sidebarPosition: SettingsData.SidebarTabBarPosition
1818

19+
@AppSettings(\.developerSettings.showInternalDevelopmentInspector)
20+
var showInternalDevelopmentInspector
21+
1922
init(viewModel: InspectorAreaViewModel) {
2023
self.viewModel = viewModel
24+
updateTabs()
25+
}
2126

22-
viewModel.tabItems = [.file, .gitHistory] +
23-
extensionManager
24-
.extensions
25-
.map { ext in
26-
ext.availableFeatures.compactMap {
27-
if case .sidebarItem(let data) = $0, data.kind == .inspector {
28-
return InspectorTab.uiExtension(endpoint: ext.endpoint, data: data)
29-
}
30-
return nil
27+
private func updateTabs() {
28+
var tabs: [InspectorTab] = [.file, .gitHistory]
29+
30+
if showInternalDevelopmentInspector {
31+
tabs.append(.internalDevelopment)
32+
}
33+
34+
viewModel.tabItems = tabs + extensionManager
35+
.extensions
36+
.map { ext in
37+
ext.availableFeatures.compactMap {
38+
if case .sidebarItem(let data) = $0, data.kind == .inspector {
39+
return InspectorTab.uiExtension(endpoint: ext.endpoint, data: data)
3140
}
41+
return nil
3242
}
33-
.joined()
43+
}
44+
.joined()
3445
}
3546

3647
var body: some View {
@@ -43,5 +54,8 @@ struct InspectorAreaView: View {
4354
.formStyle(.grouped)
4455
.accessibilityElement(children: .contain)
4556
.accessibilityLabel("inspector")
57+
.onChange(of: showInternalDevelopmentInspector) { _ in
58+
updateTabs()
59+
}
4660
}
4761
}

CodeEdit/Features/Settings/Pages/DeveloperSettings/DeveloperSettingsView.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,15 @@ struct DeveloperSettingsView: View {
1313
@AppSettings(\.developerSettings.lspBinaries)
1414
var lspBinaries
1515

16+
@AppSettings(\.developerSettings.showInternalDevelopmentInspector)
17+
var showInternalDevelopmentInspector
18+
1619
var body: some View {
1720
SettingsForm {
21+
Section {
22+
Toggle("Show Internal Development Inspector", isOn: $showInternalDevelopmentInspector)
23+
}
24+
1825
Section {
1926
KeyValueTable(
2027
items: $lspBinaries,

CodeEdit/Features/Settings/Pages/DeveloperSettings/Models/DeveloperSettings.swift

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,18 @@ extension SettingsData {
1515
[
1616
"Developer",
1717
"Language Server Protocol",
18-
"LSP Binaries"
18+
"LSP Binaries",
19+
"Show Internal Development Inspector"
1920
]
2021
.map { NSLocalizedString($0, comment: "") }
2122
}
2223

2324
/// A dictionary that stores a file type and a path to an LSP binary
2425
var lspBinaries: [String: String] = [:]
2526

27+
/// Toggle for showing the internal development inspector
28+
var showInternalDevelopmentInspector: Bool = false
29+
2630
/// Default initializer
2731
init() {}
2832

@@ -34,6 +38,11 @@ extension SettingsData {
3438
[String: String].self,
3539
forKey: .lspBinaries
3640
) ?? [:]
41+
42+
self.showInternalDevelopmentInspector = try container.decodeIfPresent(
43+
Bool.self,
44+
forKey: .showInternalDevelopmentInspector
45+
) ?? false
3746
}
3847
}
3948
}

0 commit comments

Comments
 (0)