Skip to content

Commit a7dbb60

Browse files
committed
use fluid menu bar, resize icons
1 parent 09bcf7c commit a7dbb60

File tree

14 files changed

+227
-71
lines changed

14 files changed

+227
-71
lines changed

Desktop.xcodeproj/project.pbxproj

+20
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@
66
objectVersion = 77;
77
objects = {
88

9+
/* Begin PBXBuildFile section */
10+
AA05870A2CFF16CA00A01A13 /* FluidMenuBarExtra in Frameworks */ = {isa = PBXBuildFile; productRef = AA0587092CFF16CA00A01A13 /* FluidMenuBarExtra */; };
11+
/* End PBXBuildFile section */
12+
913
/* Begin PBXContainerItemProxy section */
1014
AA06D4802CF59842002ECE92 /* PBXContainerItemProxy */ = {
1115
isa = PBXContainerItemProxy;
@@ -52,6 +56,7 @@
5256
isa = PBXFrameworksBuildPhase;
5357
buildActionMask = 2147483647;
5458
files = (
59+
AA05870A2CFF16CA00A01A13 /* FluidMenuBarExtra in Frameworks */,
5560
);
5661
runOnlyForDeploymentPostprocessing = 0;
5762
};
@@ -113,6 +118,7 @@
113118
);
114119
name = Desktop;
115120
packageProductDependencies = (
121+
AA0587092CFF16CA00A01A13 /* FluidMenuBarExtra */,
116122
);
117123
productName = desktop;
118124
productReference = AA06D46E2CF59841002ECE92 /* Desktop.app */;
@@ -198,6 +204,7 @@
198204
minimizedProjectReferenceProxies = 1;
199205
packageReferences = (
200206
AAED56702CF7326000887B28 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */,
207+
AA0587082CFF16CA00A01A13 /* XCRemoteSwiftPackageReference "fluid-menu-bar-extra" */,
201208
);
202209
preferredProjectObjectVersion = 77;
203210
productRefGroup = AA06D46F2CF59841002ECE92 /* Products */;
@@ -557,6 +564,14 @@
557564
/* End XCConfigurationList section */
558565

559566
/* Begin XCRemoteSwiftPackageReference section */
567+
AA0587082CFF16CA00A01A13 /* XCRemoteSwiftPackageReference "fluid-menu-bar-extra" */ = {
568+
isa = XCRemoteSwiftPackageReference;
569+
repositoryURL = "https://github.com/lfroms/fluid-menu-bar-extra";
570+
requirement = {
571+
kind = upToNextMajorVersion;
572+
minimumVersion = 1.1.0;
573+
};
574+
};
560575
AAED56702CF7326000887B28 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */ = {
561576
isa = XCRemoteSwiftPackageReference;
562577
repositoryURL = "https://github.com/SimplyDanny/SwiftLintPlugins";
@@ -568,6 +583,11 @@
568583
/* End XCRemoteSwiftPackageReference section */
569584

570585
/* Begin XCSwiftPackageProductDependency section */
586+
AA0587092CFF16CA00A01A13 /* FluidMenuBarExtra */ = {
587+
isa = XCSwiftPackageProductDependency;
588+
package = AA0587082CFF16CA00A01A13 /* XCRemoteSwiftPackageReference "fluid-menu-bar-extra" */;
589+
productName = FluidMenuBarExtra;
590+
};
571591
AAED56712CF7332C00887B28 /* SwiftLintBuildToolPlugin */ = {
572592
isa = XCSwiftPackageProductDependency;
573593
package = AAED56702CF7326000887B28 /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */;

Desktop.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,15 @@
11
{
2-
"originHash" : "1fa961aa1dc717cea452f3389668f0f99a254f07e4eb11d190768a53798f744f",
2+
"originHash" : "ba5cc6c48f18a191bfc7dfa34832790cdb9026b6a8f9b71b6dfe43cd35602671",
33
"pins" : [
4+
{
5+
"identity" : "fluid-menu-bar-extra",
6+
"kind" : "remoteSourceControl",
7+
"location" : "https://github.com/lfroms/fluid-menu-bar-extra",
8+
"state" : {
9+
"revision" : "e152a3a1a25aca24906217f8d4d63afbb08d7f97",
10+
"version" : "1.1.0"
11+
}
12+
},
413
{
514
"identity" : "swiftlintplugins",
615
"kind" : "remoteSourceControl",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<Scheme
3+
LastUpgradeVersion = "1610"
4+
version = "1.7">
5+
<BuildAction
6+
parallelizeBuildables = "YES"
7+
buildImplicitDependencies = "YES"
8+
buildArchitectures = "Automatic">
9+
<BuildActionEntries>
10+
<BuildActionEntry
11+
buildForTesting = "YES"
12+
buildForRunning = "YES"
13+
buildForProfiling = "YES"
14+
buildForArchiving = "YES"
15+
buildForAnalyzing = "YES">
16+
<BuildableReference
17+
BuildableIdentifier = "primary"
18+
BlueprintIdentifier = "AA06D46D2CF59841002ECE92"
19+
BuildableName = "Desktop.app"
20+
BlueprintName = "Desktop"
21+
ReferencedContainer = "container:Desktop.xcodeproj">
22+
</BuildableReference>
23+
</BuildActionEntry>
24+
</BuildActionEntries>
25+
</BuildAction>
26+
<TestAction
27+
buildConfiguration = "Debug"
28+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
29+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
30+
shouldUseLaunchSchemeArgsEnv = "YES"
31+
shouldAutocreateTestPlan = "YES">
32+
<Testables>
33+
<TestableReference
34+
skipped = "NO"
35+
parallelizable = "YES">
36+
<BuildableReference
37+
BuildableIdentifier = "primary"
38+
BlueprintIdentifier = "AA06D47E2CF59842002ECE92"
39+
BuildableName = "DesktopTests.xctest"
40+
BlueprintName = "DesktopTests"
41+
ReferencedContainer = "container:Desktop.xcodeproj">
42+
</BuildableReference>
43+
</TestableReference>
44+
<TestableReference
45+
skipped = "NO"
46+
parallelizable = "YES">
47+
<BuildableReference
48+
BuildableIdentifier = "primary"
49+
BlueprintIdentifier = "AA06D4882CF59842002ECE92"
50+
BuildableName = "DesktopUITests.xctest"
51+
BlueprintName = "DesktopUITests"
52+
ReferencedContainer = "container:Desktop.xcodeproj">
53+
</BuildableReference>
54+
</TestableReference>
55+
</Testables>
56+
</TestAction>
57+
<LaunchAction
58+
buildConfiguration = "Debug"
59+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
60+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
61+
launchStyle = "0"
62+
useCustomWorkingDirectory = "NO"
63+
ignoresPersistentStateOnLaunch = "NO"
64+
debugDocumentVersioning = "YES"
65+
debugServiceExtension = "internal"
66+
allowLocationSimulation = "YES">
67+
<BuildableProductRunnable
68+
runnableDebuggingMode = "0">
69+
<BuildableReference
70+
BuildableIdentifier = "primary"
71+
BlueprintIdentifier = "AA06D46D2CF59841002ECE92"
72+
BuildableName = "Desktop.app"
73+
BlueprintName = "Desktop"
74+
ReferencedContainer = "container:Desktop.xcodeproj">
75+
</BuildableReference>
76+
</BuildableProductRunnable>
77+
</LaunchAction>
78+
<ProfileAction
79+
buildConfiguration = "Release"
80+
shouldUseLaunchSchemeArgsEnv = "YES"
81+
savedToolIdentifier = ""
82+
useCustomWorkingDirectory = "NO"
83+
debugDocumentVersioning = "YES">
84+
<BuildableProductRunnable
85+
runnableDebuggingMode = "0">
86+
<BuildableReference
87+
BuildableIdentifier = "primary"
88+
BlueprintIdentifier = "AA06D46D2CF59841002ECE92"
89+
BuildableName = "Desktop.app"
90+
BlueprintName = "Desktop"
91+
ReferencedContainer = "container:Desktop.xcodeproj">
92+
</BuildableReference>
93+
</BuildableProductRunnable>
94+
</ProfileAction>
95+
<AnalyzeAction
96+
buildConfiguration = "Debug">
97+
</AnalyzeAction>
98+
<ArchiveAction
99+
buildConfiguration = "Release"
100+
revealArchiveInOrganizer = "YES">
101+
</ArchiveAction>
102+
</Scheme>

Desktop/AgentRow.swift

+8-3
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,12 @@ struct AgentRow: Identifiable, Equatable {
55
let name: String
66
let status: Color
77
let copyableDNS: String
8+
let workspaceName: String
89
}
910

1011
struct AgentRowView: View {
1112
let workspace: AgentRow
13+
let baseAccessURL: URL
1214
@State private var nameIsSelected: Bool = false
1315
@State private var copyIsSelected: Bool = false
1416

@@ -21,11 +23,14 @@ struct AgentRowView: View {
2123
return formattedName
2224
}
2325

26+
private var wsURL: URL {
27+
// TODO: CoderVPN currently only supports owned workspaces
28+
return baseAccessURL.appending(path: "@me").appending(path: workspace.workspaceName)
29+
}
30+
2431
var body: some View {
2532
HStack(spacing: 0) {
26-
Button {
27-
// TODO: Action
28-
} label: {
33+
Link(destination: wsURL) {
2934
HStack(spacing: 10) {
3035
ZStack {
3136
Circle()

Desktop/AppDelegate.swift

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import SwiftUI
2+
import FluidMenuBarExtra
3+
4+
class AppDelegate: NSObject, NSApplicationDelegate {
5+
private var menuBarExtra: FluidMenuBarExtra?
6+
// TODO: Replace with real VPN service
7+
private var store = PreviewVPN()
8+
9+
func applicationDidFinishLaunching(_ notification: Notification) {
10+
self.menuBarExtra = FluidMenuBarExtra(title: "Coder Desktop", image: "MenuBarIcon") {
11+
VPNMenu(
12+
vpnService: self.store
13+
).frame(width: 256)
14+
}
15+
}
16+
}

Desktop/Assets.xcassets/MenuBarIcon.imageset/Contents.json

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
{
22
"images" : [
33
{
4-
"filename" : "coder_icon.png",
4+
"filename" : "coder_icon_16.png",
55
"idiom" : "mac",
66
"scale" : "1x"
77
},
88
{
9-
"filename" : "coder_icon.png",
9+
"filename" : "coder_icon_32.png",
1010
"idiom" : "mac",
1111
"scale" : "2x"
1212
}
Binary file not shown.

Desktop/ButtonRow.swift

+11-16
Original file line numberDiff line numberDiff line change
@@ -3,23 +3,18 @@ import SwiftUI
33
struct ButtonRowView<Label: View>: View {
44
@State private var isSelected: Bool = false
55
@ViewBuilder var label: () -> Label
6-
var action: () -> Void
76

87
var body: some View {
9-
Button {
10-
action()
11-
} label: {
12-
HStack(spacing: 0) {
13-
label()
14-
Spacer()
15-
}
16-
.padding(.horizontal, 10)
17-
.frame(minHeight: 22)
18-
.frame(maxWidth: .infinity, alignment: .leading)
19-
.foregroundStyle(isSelected ? Color.white : .primary)
20-
.background(isSelected ? Color.accentColor.opacity(0.8) : .clear)
21-
.clipShape(.rect(cornerRadius: 4))
22-
.onHover { hovering in isSelected = hovering }
23-
}.buttonStyle(.plain)
8+
HStack(spacing: 0) {
9+
label()
10+
Spacer()
11+
}
12+
.padding(.horizontal, 10)
13+
.frame(minHeight: 22)
14+
.frame(maxWidth: .infinity, alignment: .leading)
15+
.foregroundStyle(isSelected ? Color.white : .primary)
16+
.background(isSelected ? Color.accentColor.opacity(0.8) : .clear)
17+
.clipShape(.rect(cornerRadius: 4))
18+
.onHover { hovering in isSelected = hovering }
2419
}
2520
}

Desktop/CoderVPN.swift

+2-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ import SwiftUI
22

33
protocol CoderVPN: ObservableObject {
44
var state: CoderVPNState { get }
5-
var data: [AgentRow] { get }
5+
var agents: [AgentRow] { get }
6+
var baseAccessURL: URL { get }
67
func start() async
78
func stop() async
89
}

Desktop/DesktopApp.swift

+7-11
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,14 @@
11
import SwiftUI
2+
import FluidMenuBarExtra
23

34
@main
45
struct DesktopApp: App {
6+
@NSApplicationDelegateAdaptor private var appDelegate: AppDelegate
7+
@State private var hidden: Bool = false
8+
59
var body: some Scene {
6-
MenuBarExtra {
7-
VPNMenu(vpnService: PreviewVPN()).frame(width: 256)
8-
} label: {
9-
let image: NSImage = {
10-
let ratio = $0.size.height / $0.size.width
11-
$0.size.height = 18
12-
$0.size.width = 18 / ratio
13-
return $0
14-
}(NSImage(named: "MenuBarIcon")!)
15-
Image(nsImage: image)
16-
}.menuBarExtraStyle(.window)
10+
MenuBarExtra("", isInserted: $hidden) {
11+
EmptyView()
12+
}
1713
}
1814
}

Desktop/Preview Content/PreviewVPN.swift

+16-11
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,22 @@ import SwiftUI
22

33
class PreviewVPN: Desktop.CoderVPN {
44
@Published var state: Desktop.CoderVPNState = .disabled
5-
@Published var data: [Desktop.AgentRow] = [
6-
AgentRow(id: UUID(), name: "dogfood2", status: .red, copyableDNS: "asdf.coder"),
7-
AgentRow(id: UUID(), name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder"),
8-
AgentRow(id: UUID(), name: "opensrc", status: .yellow, copyableDNS: "asdf.coder"),
9-
AgentRow(id: UUID(), name: "gvisor", status: .gray, copyableDNS: "asdf.coder"),
10-
AgentRow(id: UUID(), name: "example", status: .gray, copyableDNS: "asdf.coder"),
11-
AgentRow(id: UUID(), name: "dogfood2", status: .red, copyableDNS: "asdf.coder"),
12-
AgentRow(id: UUID(), name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder"),
13-
AgentRow(id: UUID(), name: "opensrc", status: .yellow, copyableDNS: "asdf.coder"),
14-
AgentRow(id: UUID(), name: "gvisor", status: .gray, copyableDNS: "asdf.coder"),
15-
AgentRow(id: UUID(), name: "example", status: .gray, copyableDNS: "asdf.coder"),
5+
@Published var baseAccessURL: URL = URL(string: "https://dev.coder.com")!
6+
@Published var agents: [Desktop.AgentRow] = [
7+
AgentRow(id: UUID(), name: "dogfood2", status: .red, copyableDNS: "asdf.coder", workspaceName: "dogfood2"),
8+
AgentRow(id: UUID(), name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder",
9+
workspaceName: "testing-a-very-long-name"
10+
),
11+
AgentRow(id: UUID(), name: "opensrc", status: .yellow, copyableDNS: "asdf.coder", workspaceName: "opensrc"),
12+
AgentRow(id: UUID(), name: "gvisor", status: .gray, copyableDNS: "asdf.coder", workspaceName: "gvisor"),
13+
AgentRow(id: UUID(), name: "example", status: .gray, copyableDNS: "asdf.coder", workspaceName: "example"),
14+
AgentRow(id: UUID(), name: "dogfood2", status: .red, copyableDNS: "asdf.coder", workspaceName: "dogfood2"),
15+
AgentRow(id: UUID(), name: "testing-a-very-long-name", status: .green, copyableDNS: "asdf.coder",
16+
workspaceName: "testing-a-very-long-name"
17+
),
18+
AgentRow(id: UUID(), name: "opensrc", status: .yellow, copyableDNS: "asdf.coder", workspaceName: "opensrc"),
19+
AgentRow(id: UUID(), name: "gvisor", status: .gray, copyableDNS: "asdf.coder", workspaceName: "gvisor"),
20+
AgentRow(id: UUID(), name: "example", status: .gray, copyableDNS: "asdf.coder", workspaceName: "example"),
1621
]
1722
let shouldFail: Bool
1823

0 commit comments

Comments
 (0)