Skip to content

Commit c070ac7

Browse files
feat: add login flow & session management (#10)
Closes #3. Relates to #4.
1 parent 2c1e8d3 commit c070ac7

30 files changed

+1123
-240
lines changed

Coder Desktop/.swiftlint.yml

+2
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,5 @@ disabled_rules:
33
- trailing_comma
44
type_name:
55
allowed_symbols: "_"
6+
identifier_name:
7+
allowed_symbols: "_"

Coder Desktop/Coder Desktop.xcodeproj/project.pbxproj

+19
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
AA8BC3392D0060A900E1ABAA /* ViewInspector in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC3382D0060A900E1ABAA /* ViewInspector */; };
1313
AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC33E2D0061F200E1ABAA /* FluidMenuBarExtra */; };
1414
AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */ = {isa = PBXBuildFile; productRef = AA8BC4CE2D00A4B700E1ABAA /* KeychainAccess */; };
15+
AAD720D02D0816B200F6304D /* Alamofire in Frameworks */ = {isa = PBXBuildFile; productRef = AAD720CF2D0816B200F6304D /* Alamofire */; };
1516
/* End PBXBuildFile section */
1617

1718
/* Begin PBXContainerItemProxy section */
@@ -101,6 +102,7 @@
101102
isa = PBXFrameworksBuildPhase;
102103
buildActionMask = 2147483647;
103104
files = (
105+
AAD720D02D0816B200F6304D /* Alamofire in Frameworks */,
104106
AA8BC4CF2D00A4B700E1ABAA /* KeychainAccess in Frameworks */,
105107
AA8BC33F2D0061F200E1ABAA /* FluidMenuBarExtra in Frameworks */,
106108
);
@@ -188,6 +190,7 @@
188190
packageProductDependencies = (
189191
AA8BC33E2D0061F200E1ABAA /* FluidMenuBarExtra */,
190192
AA8BC4CE2D00A4B700E1ABAA /* KeychainAccess */,
193+
AAD720CF2D0816B200F6304D /* Alamofire */,
191194
);
192195
productName = "Coder Desktop";
193196
productReference = 961678FC2CFF100D00B2B6DF /* Coder Desktop.app */;
@@ -302,6 +305,7 @@
302305
AA8BC33A2D0060C500E1ABAA /* XCRemoteSwiftPackageReference "SwiftLintPlugins" */,
303306
AA8BC33D2D0061F200E1ABAA /* XCRemoteSwiftPackageReference "fluid-menu-bar-extra" */,
304307
AA8BC4CD2D00A4B700E1ABAA /* XCRemoteSwiftPackageReference "KeychainAccess" */,
308+
AAD720CE2D0816B200F6304D /* XCRemoteSwiftPackageReference "Alamofire" */,
305309
);
306310
preferredProjectObjectVersion = 77;
307311
productRefGroup = 961678FD2CFF100D00B2B6DF /* Products */;
@@ -533,6 +537,7 @@
533537
ENABLE_HARDENED_RUNTIME = YES;
534538
ENABLE_PREVIEWS = YES;
535539
GENERATE_INFOPLIST_FILE = YES;
540+
INFOPLIST_KEY_LSUIElement = YES;
536541
INFOPLIST_KEY_NSHumanReadableCopyright = "";
537542
LD_RUNPATH_SEARCH_PATHS = (
538543
"$(inherited)",
@@ -561,6 +566,7 @@
561566
ENABLE_HARDENED_RUNTIME = YES;
562567
ENABLE_PREVIEWS = YES;
563568
GENERATE_INFOPLIST_FILE = YES;
569+
INFOPLIST_KEY_LSUIElement = YES;
564570
INFOPLIST_KEY_NSHumanReadableCopyright = "";
565571
LD_RUNPATH_SEARCH_PATHS = (
566572
"$(inherited)",
@@ -778,6 +784,14 @@
778784
kind = branch;
779785
};
780786
};
787+
AAD720CE2D0816B200F6304D /* XCRemoteSwiftPackageReference "Alamofire" */ = {
788+
isa = XCRemoteSwiftPackageReference;
789+
repositoryURL = "https://github.com/Alamofire/Alamofire";
790+
requirement = {
791+
kind = upToNextMajorVersion;
792+
minimumVersion = 5.10.2;
793+
};
794+
};
781795
/* End XCRemoteSwiftPackageReference section */
782796

783797
/* Begin XCSwiftPackageProductDependency section */
@@ -801,6 +815,11 @@
801815
package = AA8BC4CD2D00A4B700E1ABAA /* XCRemoteSwiftPackageReference "KeychainAccess" */;
802816
productName = KeychainAccess;
803817
};
818+
AAD720CF2D0816B200F6304D /* Alamofire */ = {
819+
isa = XCSwiftPackageProductDependency;
820+
package = AAD720CE2D0816B200F6304D /* XCRemoteSwiftPackageReference "Alamofire" */;
821+
productName = Alamofire;
822+
};
804823
/* End XCSwiftPackageProductDependency section */
805824
};
806825
rootObject = 961678F42CFF100D00B2B6DF /* Project object */;

Coder Desktop/Coder 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" : "726475d6c2c0355de7a4de72708853eaf53eb295e791efe2cc4b8eb5ce4e9ae8",
2+
"originHash" : "42dc2e0a0e0417a7f4f62b3e875c9559038beef7d2265073dd4fc81f2e11ee13",
33
"pins" : [
4+
{
5+
"identity" : "alamofire",
6+
"kind" : "remoteSourceControl",
7+
"location" : "https://github.com/Alamofire/Alamofire",
8+
"state" : {
9+
"revision" : "513364f870f6bfc468f9d2ff0a95caccc10044c5",
10+
"version" : "5.10.2"
11+
}
12+
},
413
{
514
"identity" : "fluid-menu-bar-extra",
615
"kind" : "remoteSourceControl",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
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 = "961678FB2CFF100D00B2B6DF"
19+
BuildableName = "Coder Desktop.app"
20+
BlueprintName = "Coder Desktop"
21+
ReferencedContainer = "container:Coder 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+
<TestPlans>
32+
<TestPlanReference
33+
reference = "container:Coder Desktop.xctestplan"
34+
default = "YES">
35+
</TestPlanReference>
36+
</TestPlans>
37+
<Testables>
38+
<TestableReference
39+
skipped = "NO"
40+
parallelizable = "NO">
41+
<BuildableReference
42+
BuildableIdentifier = "primary"
43+
BlueprintIdentifier = "9616790E2CFF100E00B2B6DF"
44+
BuildableName = "Coder DesktopTests.xctest"
45+
BlueprintName = "Coder DesktopTests"
46+
ReferencedContainer = "container:Coder Desktop.xcodeproj">
47+
</BuildableReference>
48+
</TestableReference>
49+
<TestableReference
50+
skipped = "NO"
51+
parallelizable = "YES">
52+
<BuildableReference
53+
BuildableIdentifier = "primary"
54+
BlueprintIdentifier = "961679182CFF100E00B2B6DF"
55+
BuildableName = "Coder DesktopUITests.xctest"
56+
BlueprintName = "Coder DesktopUITests"
57+
ReferencedContainer = "container:Coder Desktop.xcodeproj">
58+
</BuildableReference>
59+
</TestableReference>
60+
</Testables>
61+
</TestAction>
62+
<LaunchAction
63+
buildConfiguration = "Debug"
64+
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
65+
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
66+
launchStyle = "0"
67+
useCustomWorkingDirectory = "NO"
68+
ignoresPersistentStateOnLaunch = "NO"
69+
debugDocumentVersioning = "YES"
70+
debugServiceExtension = "internal"
71+
allowLocationSimulation = "YES">
72+
<BuildableProductRunnable
73+
runnableDebuggingMode = "0">
74+
<BuildableReference
75+
BuildableIdentifier = "primary"
76+
BlueprintIdentifier = "961678FB2CFF100D00B2B6DF"
77+
BuildableName = "Coder Desktop.app"
78+
BlueprintName = "Coder Desktop"
79+
ReferencedContainer = "container:Coder Desktop.xcodeproj">
80+
</BuildableReference>
81+
</BuildableProductRunnable>
82+
</LaunchAction>
83+
<ProfileAction
84+
buildConfiguration = "Release"
85+
shouldUseLaunchSchemeArgsEnv = "YES"
86+
savedToolIdentifier = ""
87+
useCustomWorkingDirectory = "NO"
88+
debugDocumentVersioning = "YES">
89+
<BuildableProductRunnable
90+
runnableDebuggingMode = "0">
91+
<BuildableReference
92+
BuildableIdentifier = "primary"
93+
BlueprintIdentifier = "961678FB2CFF100D00B2B6DF"
94+
BuildableName = "Coder Desktop.app"
95+
BlueprintName = "Coder Desktop"
96+
ReferencedContainer = "container:Coder Desktop.xcodeproj">
97+
</BuildableReference>
98+
</BuildableProductRunnable>
99+
</ProfileAction>
100+
<AnalyzeAction
101+
buildConfiguration = "Debug">
102+
</AnalyzeAction>
103+
<ArchiveAction
104+
buildConfiguration = "Release"
105+
revealArchiveInOrganizer = "YES">
106+
</ArchiveAction>
107+
</Scheme>
+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
{
2+
"configurations" : [
3+
{
4+
"id" : "BB7F7563-199E-4896-BCDE-1F751C24B71F",
5+
"name" : "Test Scheme Action",
6+
"options" : {
7+
8+
}
9+
}
10+
],
11+
"defaultOptions" : {
12+
"targetForVariableExpansion" : {
13+
"containerPath" : "container:Coder Desktop.xcodeproj",
14+
"identifier" : "961678FB2CFF100D00B2B6DF",
15+
"name" : "Coder Desktop"
16+
}
17+
},
18+
"testTargets" : [
19+
{
20+
"parallelizable" : true,
21+
"target" : {
22+
"containerPath" : "container:Coder Desktop.xcodeproj",
23+
"identifier" : "9616790E2CFF100E00B2B6DF",
24+
"name" : "Coder DesktopTests"
25+
}
26+
},
27+
{
28+
"parallelizable" : true,
29+
"target" : {
30+
"containerPath" : "container:Coder Desktop.xcodeproj",
31+
"identifier" : "961679182CFF100E00B2B6DF",
32+
"name" : "Coder DesktopUITests"
33+
}
34+
}
35+
],
36+
"version" : 1
37+
}
+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
import SwiftUI
2+
3+
enum About {
4+
private static var credits: NSAttributedString {
5+
let coder = NSMutableAttributedString(
6+
string: "Coder.com",
7+
attributes: [
8+
.foregroundColor: NSColor.labelColor,
9+
.link: NSURL(string: "https://coder.com")!,
10+
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
11+
]
12+
)
13+
let separator = NSAttributedString(
14+
string: " | ",
15+
attributes: [
16+
.foregroundColor: NSColor.labelColor,
17+
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
18+
]
19+
)
20+
let source = NSAttributedString(
21+
string: "GitHub",
22+
attributes: [
23+
.foregroundColor: NSColor.labelColor,
24+
.link: NSURL(string: "https://github.com/coder/coder-desktop-macos")!,
25+
.font: NSFont.systemFont(ofSize: NSFont.systemFontSize),
26+
]
27+
)
28+
coder.append(separator)
29+
coder.append(source)
30+
return coder
31+
}
32+
33+
static func open() {
34+
#if compiler(>=5.9) && canImport(AppKit)
35+
if #available(macOS 14, *) {
36+
NSApp.activate()
37+
} else {
38+
NSApp.activate(ignoringOtherApps: true)
39+
}
40+
#else
41+
NSApp.activate(ignoringOtherApps: true)
42+
#endif
43+
NSApp.orderFrontStandardAboutPanel(options: [
44+
.credits: credits,
45+
])
46+
}
47+
}
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import SwiftUI
21
import FluidMenuBarExtra
2+
import SwiftUI
33

44
@main
55
struct DesktopApp: App {
@@ -10,21 +10,33 @@ struct DesktopApp: App {
1010
MenuBarExtra("", isInserted: $hidden) {
1111
EmptyView()
1212
}
13+
Window("Sign In", id: Windows.login.rawValue) {
14+
LoginForm<PreviewClient, PreviewSession>()
15+
}.environmentObject(appDelegate.session)
16+
.windowResizability(.contentSize)
1317
}
1418
}
1519

1620
class AppDelegate: NSObject, NSApplicationDelegate {
1721
private var menuBarExtra: FluidMenuBarExtra?
18-
// TODO: Replace with real implementations
19-
private var vpn = PreviewVPN()
20-
private var session = PreviewSession()
22+
let vpn: PreviewVPN
23+
let session: PreviewSession
24+
25+
override init() {
26+
// TODO: Replace with real implementations
27+
vpn = PreviewVPN()
28+
session = PreviewSession()
29+
}
2130

22-
func applicationDidFinishLaunching(_ notification: Notification) {
23-
self.menuBarExtra = FluidMenuBarExtra(title: "Coder Desktop", image: "MenuBarIcon") {
24-
VPNMenu(
25-
vpn: self.vpn,
26-
session: self.session
27-
).frame(width: 256)
31+
func applicationDidFinishLaunching(_: Notification) {
32+
menuBarExtra = FluidMenuBarExtra(title: "Coder Desktop", image: "MenuBarIcon") {
33+
VPNMenu<PreviewVPN, PreviewSession>().frame(width: 256)
34+
.environmentObject(self.vpn)
35+
.environmentObject(self.session)
2836
}
2937
}
38+
39+
func applicationShouldTerminateAfterLastWindowClosed(_: NSApplication) -> Bool {
40+
false
41+
}
3042
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import SwiftUI
2+
3+
struct PreviewClient: Client {
4+
init(url _: URL, token _: String? = nil) {}
5+
6+
func user(_: String) async throws -> User {
7+
try await Task.sleep(for: .seconds(1))
8+
return User(
9+
id: UUID(),
10+
username: "admin",
11+
avatar_url: "",
12+
name: "admin",
13+
14+
created_at: Date.now,
15+
updated_at: Date.now,
16+
last_seen_at: Date.now,
17+
status: "active",
18+
login_type: "none",
19+
theme_preference: "dark",
20+
organization_ids: [],
21+
roles: []
22+
)
23+
}
24+
}

Coder Desktop/Coder Desktop/Preview Content/PreviewSession.swift

+3-4
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,14 @@ class PreviewSession: Session {
1111
baseAccessURL = nil
1212
}
1313

14-
func login(baseAccessURL: URL, sessionToken: String) {
14+
func store(baseAccessURL: URL, sessionToken: String) {
1515
hasSession = true
1616
self.baseAccessURL = baseAccessURL
1717
self.sessionToken = sessionToken
1818
}
1919

20-
func logout() {
20+
func clear() {
2121
hasSession = false
22-
self.baseAccessURL = nil
23-
self.sessionToken = nil
22+
sessionToken = nil
2423
}
2524
}

0 commit comments

Comments
 (0)