File tree Expand file tree Collapse file tree 4 files changed +46
-11
lines changed Expand file tree Collapse file tree 4 files changed +46
-11
lines changed Original file line number Diff line number Diff line change @@ -40,11 +40,21 @@ class AppDelegate: NSObject, NSApplicationDelegate {
4040 }
4141
4242 func applicationDidFinishLaunching( _: Notification ) {
43- menuBar = . init( menuBarExtra: FluidMenuBarExtra ( title: " Coder Desktop " , image: " MenuBarIcon " ) {
44- VPNMenu < CoderVPNService > ( ) . frame ( width: 256 )
45- . environmentObject ( self . vpn)
46- . environmentObject ( self . state)
47- } )
43+ menuBar = . init( menuBarExtra: FluidMenuBarExtra (
44+ title: " Coder Desktop " ,
45+ image: " MenuBarIcon " ,
46+ onAppear: {
47+ // If the VPN is enabled, it's likely the token isn't expired
48+ guard case . disabled = self . vpn. state, self . state. hasSession else { return }
49+ Task { @MainActor in
50+ await self . state. handleTokenExpiry ( )
51+ }
52+ } , content: {
53+ VPNMenu < CoderVPNService > ( ) . frame ( width: 256 )
54+ . environmentObject ( self . vpn)
55+ . environmentObject ( self . state)
56+ }
57+ ) )
4858 // Subscribe to system VPN updates
4959 NotificationCenter . default. addObserver (
5060 self ,
Original file line number Diff line number Diff line change @@ -2,10 +2,12 @@ import CoderSDK
22import Foundation
33import KeychainAccess
44import NetworkExtension
5+ import os
56import SwiftUI
67
78@MainActor
89class AppState : ObservableObject {
10+ private let logger = Logger ( subsystem: Bundle . main. bundleIdentifier!, category: " AppState " )
911 let appId = Bundle . main. bundleIdentifier!
1012
1113 // Stored in UserDefaults
@@ -95,6 +97,9 @@ class AppState: ObservableObject {
9597 )
9698 if hasSession {
9799 _sessionToken = Published ( initialValue: keychainGet ( for: Keys . sessionToken) )
100+ if sessionToken == nil || sessionToken!. isEmpty == true {
101+ clearSession ( )
102+ }
98103 }
99104 }
100105
@@ -105,6 +110,24 @@ class AppState: ObservableObject {
105110 reconfigure ( )
106111 }
107112
113+ public func handleTokenExpiry( ) async {
114+ if hasSession {
115+ let client = Client ( url: baseAccessURL!, token: sessionToken!)
116+ do {
117+ _ = try await client. user ( " me " )
118+ } catch let ClientError . api( apiErr) {
119+ // Expired token
120+ if apiErr. statusCode == 401 {
121+ clearSession ( )
122+ }
123+ } catch {
124+ // Some other failure, we'll show an error if they try and do something
125+ logger. error ( " failed to check token validity: \( error) " )
126+ return
127+ }
128+ }
129+ }
130+
108131 public func clearSession( ) {
109132 hasSession = false
110133 sessionToken = nil
Original file line number Diff line number Diff line change @@ -104,10 +104,10 @@ public struct Client {
104104}
105105
106106public struct APIError : Decodable , Sendable {
107- let response : Response
108- let statusCode : Int
109- let method : String
110- let url : URL
107+ public let response : Response
108+ public let statusCode : Int
109+ public let method : String
110+ public let url : URL
111111
112112 var description : String {
113113 var components = [ " \( method) \( url. absoluteString) \n Unexpected status code \( statusCode) : \n \( response. message) " ]
Original file line number Diff line number Diff line change @@ -92,10 +92,12 @@ packages:
9292 url : https://github.com/SimplyDanny/SwiftLintPlugins
9393 from : 0.57.1
9494 FluidMenuBarExtra :
95- # Forked so we can dynamically update the menu bar icon.
95+ # Forked to:
96+ # - Dynamically update the menu bar icon
97+ # - Set onAppear/disappear handlers.
9698 # The upstream repo has a purposefully limited API
9799 url : https://github.com/coder/fluid-menu-bar-extra
98- revision : 020be37
100+ revision : 96a861a
99101 KeychainAccess :
100102 url : https://github.com/kishikawakatsumi/KeychainAccess
101103 branch : e0c7eebc5a4465a3c4680764f26b7a61f567cdaf
You can’t perform that action at this time.
0 commit comments